93 lines
3.6 KiB
Python
93 lines
3.6 KiB
Python
import os
|
|
import subprocess
|
|
import requests
|
|
import json
|
|
from pathlib import Path
|
|
|
|
WORKSPACE_ROOT = Path(__file__).resolve().parent.parent
|
|
OUTPUTS_DIR = WORKSPACE_ROOT / "outputs"
|
|
FINAL_VIDEO_DIR = OUTPUTS_DIR / "final_video"
|
|
TEMP_AUDIO_DIR = OUTPUTS_DIR / "temp_audio"
|
|
AUDIO_DIR = OUTPUTS_DIR / "audio"
|
|
BACKGROUNDS_DIR = WORKSPACE_ROOT / "backgrounds"
|
|
|
|
def generate_video(task_id):
|
|
from core.models import VideoTask
|
|
task = VideoTask.objects.get(id=task_id)
|
|
task.status = 'processing'
|
|
task.save()
|
|
|
|
try:
|
|
# 1. Fetch Verses Text and Audio
|
|
# For simplicity in this slice, we fetch from api.alquran.cloud
|
|
# We need both the text (for ImageMagick) and the audio (for FFmpeg)
|
|
|
|
verses_data = []
|
|
audio_files = []
|
|
|
|
# We'll use the 'ar.alafasy' or user-selected reciter
|
|
# Example: https://api.alquran.cloud/v1/surah/1/ar.alafasy
|
|
api_url = f"https://api.alquran.cloud/v1/surah/{task.surah_number}/{task.reciter_identifier}"
|
|
resp = requests.get(api_url)
|
|
resp.raise_for_status()
|
|
data = resp.json()['data']
|
|
|
|
all_ayahs = data['ayahs']
|
|
selected_ayahs = [a for a in all_ayahs if task.verse_start <= a['numberInSurah'] <= task.verse_end]
|
|
|
|
# Download audio files and prepare text
|
|
for i, ayah in enumerate(selected_ayahs):
|
|
audio_url = ayah['audio']
|
|
audio_path = TEMP_AUDIO_DIR / f"task_{task.id}_ayah_{i}.mp3"
|
|
with requests.get(audio_url, stream=True) as r:
|
|
r.raise_for_status()
|
|
with open(audio_path, 'wb') as f:
|
|
for chunk in r.iter_content(chunk_size=8192):
|
|
f.write(chunk)
|
|
audio_files.append(str(audio_path))
|
|
verses_data.append({
|
|
'text': ayah['text'],
|
|
'audio': str(audio_path)
|
|
})
|
|
|
|
# 2. Combine Audio
|
|
combined_audio = AUDIO_DIR / f"task_{task.id}_full.mp3"
|
|
# ffmpeg -i "concat:file1.mp3|file2.mp3" -acodec copy output.mp3
|
|
concat_str = "|".join(audio_files)
|
|
subprocess.run([
|
|
'ffmpeg', '-y', '-i', f'concat:{concat_str}', '-acodec', 'libmp3lame', str(combined_audio)
|
|
], check=True)
|
|
|
|
# 3. Generate Video with FFmpeg
|
|
# We use a background video and overlay the audio
|
|
bg_video = BACKGROUNDS_DIR / task.background_video
|
|
if not bg_video.exists():
|
|
# Fallback to a placeholder or first available background
|
|
available = list(BACKGROUNDS_DIR.glob("*.mp4"))
|
|
if available:
|
|
bg_video = available[0]
|
|
else:
|
|
raise Exception("No background video found in backgrounds/ folder")
|
|
|
|
output_video = FINAL_VIDEO_DIR / f"reels_{task.id}.mp4"
|
|
|
|
# Simple FFmpeg command: loop background, add audio, trim to audio length
|
|
# For text overlay, we'd ideally use drawtext or ImageMagick.
|
|
# Here we do a basic version:
|
|
subprocess.run([
|
|
'ffmpeg', '-y', '-stream_loop', '-1', '-i', str(bg_video),
|
|
'-i', str(combined_audio), '-shortest', '-map', '0:v:0', '-map', '1:a:0',
|
|
'-pix_fmt', 'yuv420p', '-vf', f"drawtext=text='{task.surah_name}':fontcolor={task.text_color}:fontsize=48:x=(w-text_w)/2:y=(h-text_h)/2",
|
|
str(output_video)
|
|
], check=True)
|
|
|
|
task.status = 'completed'
|
|
task.output_path = f"/outputs/final_video/{output_video.name}"
|
|
task.save()
|
|
|
|
except Exception as e:
|
|
task.status = 'failed'
|
|
task.error_message = str(e)
|
|
task.save()
|
|
raise e
|