Automating Content Creation with Python: Editing with MoviePy
Tags: python, api, showdev, tutorial
Published: 2023-01-25 18:52:16

This is a continuation of a multi-part series on building a YouTube content creation bot that utilizes Twitch clips. If you have yet to see it, be sure to start with the [first part](https://dev.to/viniciusenari/automating-content-creation-with-python-a-guide-to-building-a-twitch-highlights-bot-part-1-1h6m).

## Compiling the Clips into a Video

With the clips downloaded, the next step is to merge them into a single video. I used the [MoviePy](https://zulko.github.io/moviepy/) Python library. The editing process involves three steps:

1. Create overlays for each clip with the broadcaster's title and name.
2. Superimpose the overlay on the top of the corresponding clip.
3. Concatenate all the clips together to produce a single video.

This way, you will have a final video with the title, and broadcaster name on every clip and all clips merged into one video.

### Creating Overlays

I used the Python library [Pillow](https://pillow.readthedocs.io/en/stable/) to create the overlays for the clips. Although MoviePy also allows adding text to clips, it relies on the ImageMagick library, which requires manual installation. I preferred Pillow as it is easier to install, although it may be less efficient.

I made a transparent image of 1980x1080 resolution to create an overlay with Pillow. I added the title and broadcaster's name at the bottom left corner. If the title is too long, it will be truncated, and a "..." will be added to the end. After an overlay is created, it is saved in a dedicated directory.

Here's an example of the code:
```python
from PIL import Image, ImageDraw, ImageFont

def create_overlay(self, clip_content):
	title = clip_content.title
	broadcaster_name = clip_content.broadcaster_name
	if len(title) > 40: title = title[:40] + '...'

	# Create a 1980x1080 transparent image
	overlay = Image.new('RGBA', (1920, 1080), color = (255,255,255,0))

	# Load fonts and create font objects
	fnt_clip_name = ImageFont.truetype(font_clip_name, 62)
	fnt_streamer_name = ImageFont.truetype(font_broadcaster, 50)

	d = ImageDraw.Draw(overlay)

	d.text((100, 930), title, font=fnt_clip_name, stroke_width=3, stroke_fill=(0, 0, 0), fill=(255, 255, 255))
	d.text((100, 1000), broadcaster_name, font=fnt_streamer_name, stroke_width=3, stroke_fill=(0, 0, 0), fill=(255, 255, 255))

	if not os.path.exists('files/overlays'): os.makedirs('files/overlays')
	filename = clip_content.title.replace(" ", "_").replace("/","_").lower()
	overlay.save(f'files/overlays/{filename}.png')
```

### Superimposing the Overlay

Using the MoviePy library, I superimposed the overlays on the clips. The process is straightforward: I created a MoviePy [`VideoFileClip`](https://zulko.github.io/moviepy/ref/VideoClip/VideoClip.html?highlight=videofileclip#moviepy.video.io.VideoFileClip.VideoFileClip) and [`ImageClip`](https://zulko.github.io/moviepy/ref/VideoClip/VideoClip.html?highlight=imageclip#moviepy.video.VideoClip.ImageClip), for the clip and overlay. Then, I combined them into a [`CompositeVideoClip`](https://zulko.github.io/moviepy/ref/VideoClip/VideoClip.html?highlight=compositevideoclip#moviepy.video.compositing.CompositeVideoClip.CompositeVideoClip).

```python
from moviepy.editor import VideoFileClip, ImageClip, CompositeVideoClip

def create_video(self, clip_content):
	clip = VideoFileClip(clip_content.path, target_resolution=(1080, 1980))
	filename = clip_content.title.replace(" ", "_").replace("/","_").lower()
	img_clip = ImageClip(f'files/overlays/{filename}.png').set_duration(5)
	video = CompositeVideoClip([clip, img_clip])
	return video
```

Resulting in the following:
![Example clip with overlay](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mukntkrepny3fv0oxjuc.png)

### Concatenating the Clips

Now that all individual clips have an overlay, the next step is to concatenate them. The MoviePy library offers the [`concatenate_videoclips`](https://github.com/Zulko/moviepy/blob/master/moviepy/video/compositing/concatenate.py) function, which, when used on an array of MoviePy clip objects, returns a single clip composed of all the other clips played one after another. Using the `method='compose'` parameter ensures that if the clips have different resolutions, MoviePy will resize them to result in a seamless final product.

The final step is to convert the clip object into an actual video file. The [`write_videofile`](https://zulko.github.io/moviepy/ref/VideoClip/VideoClip.html?highlight=write_videofile#moviepy.video.io.VideoFileClip.VideoFileClip.write_videofile) method is used to do that. It takes various parameters such as fps, codec, threads, preset, and bitrate. The values for these parameters have been chosen after experimenting to find the best results. It's worth noting that what worked for me may not be the best for others, so one should experiment with different parameters to find the best results for their specific use case.

Here is the code for concatenating the clips. I create an overlay for each clip, superimpose it to the clip, and append it to an array. It then concatenates all clips on the array and writes a video file from the concatenated clip.
```python
from moviepy.editor import concatenate_videoclips

render_settings = {
    'fps' : 60,
    'codec' : "mpeg4",
    'threads' : 8,
    'preset' : "ultrafast",
    'bitrate' : '20000k'
}

def create_video_compilation(self, clips, amount):
	for clip in clips[:amount]:
		self.create_overlay(clip)
		self.clips.append(self.create_video(clip))

	video = concatenate_videoclips(self.clips, method='compose')
	if not os.path.exists('files/youtube'): os.makedirs('files/youtube')
	video.write_videofile(f'files/youtube/video.mp4', fps = render_settings['fps'], codec = render_settings['codec'], threads = render_settings['threads'], preset = render_settings['preset'], bitrate = render_settings['bitrate'])
```

### Conclusion

In the article, I covered how to use MoviePy to edit videos and create a compilation from before downloaded clips. In the [next part](https://dev.to/viniciusenari/automating-content-creation-with-python-a-guide-to-building-a-twitch-highlights-bot-part-4-26jn), I will cover how you can use the Youtube API to upload videos with a custom title, description, thumbnail, and tags. Remember to leave a comment if you have any questions.