File size: 2,326 Bytes
2c3ea7b
7006220
 
d53004d
2c3ea7b
d53004d
2c3ea7b
 
 
7006220
 
aec5d3a
 
 
 
 
 
 
7006220
d53004d
aec5d3a
 
7006220
2c3ea7b
7006220
d53004d
 
e2fc4a2
d53004d
e2fc4a2
d53004d
e2fc4a2
d53004d
 
 
 
2c3ea7b
d53004d
 
 
 
aec5d3a
d53004d
 
 
 
 
 
 
2c3ea7b
e2fc4a2
d53004d
 
2c3ea7b
d53004d
 
 
 
 
 
e2fc4a2
 
2c3ea7b
 
d53004d
 
2c3ea7b
d53004d
 
 
 
 
 
e2fc4a2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
import os, uuid, requests
from gtts import gTTS
from mutagen.mp3 import MP3
from moviepy.editor import ImageClip, concatenate_videoclips, AudioFileClip
from moviepy.config import change_settings

# βœ… Force MoviePy temp directory to /tmp
change_settings({"FFMPEG_BINARY": "ffmpeg"})
os.environ["TMPDIR"] = "/tmp"

def generate_video_file(script: str, duration: int = None) -> str:
    base_tmp = "/tmp/video"
    audio_tmp = "/tmp/audio"
    tmp_images = "/tmp/video_tmp"

    os.makedirs(base_tmp, exist_ok=True)
    os.makedirs(audio_tmp, exist_ok=True)
    os.makedirs(tmp_images, exist_ok=True)

    video_filename = f"video_{uuid.uuid4().hex}.mp4"
    video_path = os.path.join(base_tmp, video_filename)
    audio_path = os.path.join(audio_tmp, f"audio_{uuid.uuid4().hex}.mp3")

    # Step 1: Generate TTS audio
    tts = gTTS(text=script, lang='en')
    tts.save(audio_path)

    # Step 2: Get audio duration
    audio = MP3(audio_path)
    audio_duration = max(audio.info.length, 3.0)

    # Step 3: Fetch Unsplash images
    images = fetch_unsplash_images(script, count=3)
    if not images:
        raise Exception("No images found from Unsplash for the prompt")

    clips, tmp_files = [], []
    per_image_duration = audio_duration / len(images)

    for url in images:
        img_data = requests.get(url).content
        tmp_file = os.path.join(tmp_images, f"tmp_{uuid.uuid4().hex}.jpg")
        tmp_files.append(tmp_file)
        with open(tmp_file, "wb") as f:
            f.write(img_data)

        clip = ImageClip(tmp_file).resize(height=720).set_duration(per_image_duration)
        clips.append(clip)

    # Step 4: Build final video
    final_clip = concatenate_videoclips(clips, method="compose").set_duration(audio_duration)
    final_clip = final_clip.set_audio(AudioFileClip(audio_path))

    # βœ… Step 5: Export video with all temp files in /tmp
    final_clip.write_videofile(
        video_path,
        fps=24,
        codec="libx264",
        audio_codec="aac",
        threads=4,
        preset="ultrafast",
        temp_audiofile="/tmp/temp-audio.m4a",
        remove_temp=True,
        ffmpeg_params=["-avoid_negative_ts", "make_zero"]
    )

    # Cleanup images
    for file in tmp_files:
        try:
            os.remove(file)
        except:
            pass

    return video_filename