| 13 | |
| 14 | |
| 15 | class Video: |
| 16 | def __init__(self, frame_path: str, fps: float = 12.5, res="high"): |
| 17 | frame_path = str(frame_path) |
| 18 | self.fps = fps |
| 19 | |
| 20 | self._conf = {"codec": "libx264", |
| 21 | "fps": self.fps, |
| 22 | "audio_codec": "aac", |
| 23 | "temp_audiofile": "temp-audio.m4a", |
| 24 | "remove_temp": True} |
| 25 | |
| 26 | if res == "low": |
| 27 | bitrate = "500k" |
| 28 | else: |
| 29 | bitrate = "5000k" |
| 30 | |
| 31 | self._conf = {"bitrate": bitrate, |
| 32 | "fps": self.fps} |
| 33 | |
| 34 | # Load video |
| 35 | # video = mp.VideoFileClip(video1_path, audio=False) |
| 36 | # Load with frames |
| 37 | frames = [os.path.join(frame_path, x) |
| 38 | for x in sorted(os.listdir(frame_path))] |
| 39 | |
| 40 | # mask background white for videos |
| 41 | mask_png(frames) |
| 42 | |
| 43 | video = mp.ImageSequenceClip(frames, fps=fps) |
| 44 | self.video = video |
| 45 | self.duration = video.duration |
| 46 | |
| 47 | def add_text(self, text): |
| 48 | # needs ImageMagick |
| 49 | video_text = mp.TextClip(text, |
| 50 | font='Amiri', |
| 51 | color='white', |
| 52 | method='caption', |
| 53 | align="center", |
| 54 | size=(self.video.w, None), |
| 55 | fontsize=30) |
| 56 | video_text = video_text.on_color(size=(self.video.w, video_text.h + 5), |
| 57 | color=(0, 0, 0), |
| 58 | col_opacity=0.6) |
| 59 | # video_text = video_text.set_pos('bottom') |
| 60 | video_text = video_text.set_pos('top') |
| 61 | |
| 62 | self.video = mp.CompositeVideoClip([self.video, video_text]) |
| 63 | |
| 64 | def save(self, out_path): |
| 65 | out_path = str(out_path) |
| 66 | self.video.subclip(0, self.duration).write_videofile( |
| 67 | out_path, **self._conf) |