Skip to content

Commit 21faa8c

Browse files
committed
subtitle works
1 parent 169357c commit 21faa8c

9 files changed

Lines changed: 125 additions & 11 deletions

File tree

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
from moviepy import VideoFileClip, TextClip, CompositeVideoClip
2+
from faster_whisper import WhisperModel
3+
4+
def typewriter_subtitle(text, start, duration, fontsize=42, color='black'):
5+
clips = []
6+
total_chars = len(text)
7+
if total_chars == 0:
8+
return []
9+
10+
char_duration = duration / total_chars
11+
12+
for i in range(1, total_chars + 1):
13+
txt = text[:i] + "|" if i < total_chars else text[:i] # Blinking cursor
14+
txt_clip = (
15+
TextClip(font="./fonts/font.ttf", text=txt, font_size=fontsize, color=color)
16+
.with_position(("center", "bottom"))
17+
.with_start(start + (i - 1) * char_duration)
18+
.with_duration(char_duration)
19+
)
20+
clips.append(txt_clip)
21+
22+
return clips
23+
24+
25+
# Load video and extract audio
26+
video = VideoFileClip("./results/auto_edit.mp4")
27+
video.audio.write_audiofile("auto_audio.wav")
28+
29+
# Transcribe with faster-whisper
30+
model = WhisperModel("base") # You can use 'small' or 'medium' if needed
31+
segments, _ = model.transcribe("auto_audio.wav")
32+
print(f"Segments are: {segments}")
33+
34+
# Build typewriter subtitles for all segments
35+
subtitle_clips = []
36+
for segment in segments:
37+
typing_clips = typewriter_subtitle(
38+
segment.text, segment.start, segment.end - segment.start
39+
)
40+
subtitle_clips.extend(typing_clips)
41+
42+
print("Writing Final Video with Subtitle...")
43+
44+
# Final composite
45+
final = CompositeVideoClip([video, *subtitle_clips])
46+
final.write_videofile("./results/typewriter_subtitles.mp4", fps=24)

movie_py_explored/auto_audio.wav

18.5 MB
Binary file not shown.
Lines changed: 79 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,26 @@
1-
from moviepy import *
1+
from moviepy import * # type: ignore
22
import numpy as np
33

44
# Run the code inside the movie_py
55
# loading the base video
66
video = VideoFileClip("./example_vids/async_work.mkv")
77

8-
""" - agenda ⇒ 0.14 to 1.01
8+
"""
9+
These were changed after first run
10+
- agenda ⇒ 0.14 to 0.30
911
- dont_hire ⇒3.22 to 3.50
1012
- communication ⇒ 7:05 to 7:25
1113
- clear_process ⇒ 8:00 to 8:54
1214
- open_source ⇒ 12:44 to 13:44
13-
"""
15+
"""
1416

15-
agenda = video.subclipped(14, 61)
17+
agenda = video.subclipped(14, 30)
1618
dont_hire = video.subclipped(202, 225)
1719
communication = video.subclipped(425, 450)
1820
clearproc = video.subclipped(480, 505)
19-
opensource = video.subclipped(764, 824)
21+
opensource = video.subclipped(764, 790)
2022

23+
print(dir(agenda))
2124
# Preview the clips
2225

2326
""" agenda.preview(fps=25)
@@ -26,7 +29,7 @@
2629
clearproc.preview(fps=25)
2730
opensource.preview(fps=25) """
2831

29-
opensource = opensource.with_section_cut_out(start_time=50, end_time=70)
32+
opensource = opensource.with_section_cut_out(start_time=10, end_time=15)
3033

3134
# opensource.preview(fps=25)
3235

@@ -36,21 +39,86 @@
3639
agenda_text = TextClip(font=font,
3740
text="Agend is:",
3841
font_size=50,
39-
color="#fff")
42+
color="#000")
43+
agenda_text = agenda_text.with_position(("center", 200))
4044
dont_hire_text = TextClip(font=font,
4145
text="Think Automation before you Hire",
4246
font_size=40,
43-
color="#fff")
47+
color="#000")
48+
dont_hire_text = dont_hire_text.with_position(("center", 200))
4449
comm_text = TextClip(font=font,
4550
text="The game changer is Communication.",
4651
font_size=40,
47-
color="#fff")
52+
color="#000")
53+
comm_text = comm_text.with_position(("center", 200))
4854
clear_proc_text = TextClip(font=font,
4955
text="Setting up Process is step towards Automation.",
5056
font_size=50,
51-
color="#fff")
57+
color="#000")
58+
clear_proc_text = clear_proc_text.with_position(("center", 200))
5259
opensource_text = TextClip(font=font,
5360
text="Make it as Open Source to gain Traction.",
5461
font_size=50,
55-
color="#fff")
62+
color="#000")
63+
opensource_text.with_position(("center", 200))
5664

65+
## Adding logo clips
66+
aa = ImageClip(img="./example_vids/1F4AA.png")
67+
p4a = ImageClip(img="./example_vids/1F44A.png")
68+
p4c = ImageClip(img="./example_vids/1F44C.png")
69+
p4d = ImageClip(img="./example_vids/1F44D.png")
70+
71+
72+
## Adding the duration for the text clips
73+
74+
agenda_text = agenda_text.with_duration(8).with_start(5)
75+
aa = aa.with_start(agenda.start + 2).with_end(agenda_text.end)
76+
77+
dont_hire = dont_hire.with_start(agenda.end)
78+
dont_hire_text = dont_hire_text.with_start(dont_hire.start + 2).with_end(dont_hire.start + 10)
79+
p4a = p4a.with_start(dont_hire_text.start + 1).with_end(dont_hire_text.end)
80+
81+
communication = communication.with_start(dont_hire.end)
82+
comm_text = comm_text.with_start(communication.start+2).with_end(communication.end-10)
83+
p4c = p4c.with_start(communication.start + 4).with_duration(5)
84+
85+
clearproc = clearproc.with_start(communication.end)
86+
clear_proc_text = clear_proc_text.with_duration(5).with_start(clearproc.start + 2)
87+
88+
opensource = opensource.with_start(clearproc.end)
89+
opensource_text = opensource_text.with_duration(5).with_start(opensource.start + 2)
90+
p4d = p4d.with_start(opensource_text.start + 5).with_duration(5)
91+
92+
### First Compo
93+
94+
first_compo = CompositeVideoClip([
95+
agenda, agenda_text, aa, dont_hire, dont_hire_text, p4a,
96+
communication, comm_text, p4c,
97+
clearproc, clear_proc_text, opensource, opensource_text,
98+
p4d
99+
])
100+
101+
# first_compo.preview(fps=25)
102+
103+
agenda = agenda.with_effects([vfx.CrossFadeIn(1), vfx.CrossFadeOut(1)])
104+
dont_hire = dont_hire.with_effects([vfx.CrossFadeIn(1), vfx.CrossFadeOut(1)])
105+
communication = communication.with_effects([vfx.CrossFadeIn(1), vfx.CrossFadeOut(1)])
106+
clearproc = clearproc.with_effects([vfx.CrossFadeIn(1), vfx.CrossFadeOut(1)])
107+
opensource = opensource.with_effects([vfx.CrossFadeIn(1), vfx.CrossFadeOut(1)])
108+
109+
agenda_text = agenda_text.with_effects([vfx.FadeIn(1), vfx.FadeOut(1)])
110+
dont_hire_text = dont_hire_text.with_effects([vfx.FadeIn(1), vfx.FadeOut(1)])
111+
comm_text = comm_text.with_effects([vfx.FadeIn(1), vfx.FadeOut(1)])
112+
clear_proc_text = clear_proc_text.with_effects([vfx.FadeIn(1), vfx.FadeOut(1)])
113+
opensource_text = opensource_text.with_effects([vfx.FadeIn(1), vfx.FadeOut(1)])
114+
115+
second_compo = CompositeVideoClip([
116+
agenda, agenda_text, aa, dont_hire, dont_hire_text, p4a,
117+
communication, comm_text, p4c,
118+
clearproc, clear_proc_text, opensource, opensource_text,
119+
p4d
120+
])
121+
122+
# second_compo.preview(fps=25)
123+
124+
second_compo.write_videofile("./results/auto_edit.mp4")
9.19 KB
Loading
14 KB
Loading
8.77 KB
Loading
14.5 KB
Loading
3.41 MB
Binary file not shown.
4.25 MB
Binary file not shown.

0 commit comments

Comments
 (0)