Renders a video based on a project.
Parameters:
| Name |
Type |
Description |
Default |
project
|
VideoProject
|
|
required
|
output_path
|
str | Path
|
The output path. If a directory is provided, the output file will be saved in the directory with the project title as the filename. Otherwise, be sure that the file extension matches the codec used. By default, the output file will be an MP4 file (H.264 codec). The available codecs are: - libx264: .mp4 - mpeg4: .mp4 - rawvideo: .avi - png: .avi - libvorbis: .ogv - libvpx: .webm
|
required
|
overwrite
|
bool
|
Whether to overwrite the output file if it already exists.
|
False
|
kwargs
|
Any
|
Additional keyword arguments to pass to Moviepy clip video writer.
|
{}
|
Returns:
| Type |
Description |
Path
|
The path to the rendered video.
|
Source code in src/mosaico/video/rendering.py
| def render_video(
project: VideoProject,
output_path: str | Path,
*,
overwrite: bool = False,
**kwargs: Any,
) -> Path:
"""
Renders a video based on a project.
:param project: The project to render.
:param output_path: The output path. If a directory is provided, the output file will be saved in the directory
with the project title as the filename. Otherwise, be sure that the file extension matches the codec used.
By default, the output file will be an MP4 file (H.264 codec). The available codecs are:
- libx264: .mp4
- mpeg4: .mp4
- rawvideo: .avi
- png: .avi
- libvorbis: .ogv
- libvpx: .webm
:param overwrite: Whether to overwrite the output file if it already exists.
:param kwargs: Additional keyword arguments to pass to Moviepy clip video writer.
:return: The path to the rendered video.
"""
output_path = Path(output_path).resolve()
output_codec = kwargs.get("codec") or _guess_codec_from_file_path(output_path) or "libx264"
output_file_ext = _CODEC_FILE_EXTENSION_MAP[output_codec]
if output_path.is_dir():
output_path /= f"{project.config.title}.{output_file_ext}"
if output_path.suffix != output_file_ext:
raise ValueError(f"Output file must be an '{output_file_ext}' file.")
if not output_path.parent.exists():
raise FileNotFoundError(f"Output directory does not exist: {output_path.parent}")
if output_path.exists() and not overwrite:
msg = f"Output file already exists: {output_path}"
raise FileExistsError(msg)
video_clips = []
audio_clips = []
for event in project.timeline:
event_asset_ref_pairs = _get_event_assets_and_refs(event, project)
event_video_clips, event_audio_clips = _render_event_clips(event_asset_ref_pairs, project.config.resolution)
video_clips.extend(event_video_clips or [])
audio_clips.extend(event_audio_clips or [])
video: VideoClip = (
CompositeVideoClip(video_clips, size=project.config.resolution)
.with_fps(project.config.fps)
.with_duration(project.duration)
)
if audio_clips:
audio = CompositeAudioClip(audio_clips).with_duration(project.duration)
video = video.with_audio(audio)
kwargs["codec"] = output_codec
kwargs["audio_codec"] = kwargs.get("audio_codec", "aac")
kwargs["threads"] = kwargs.get("threads", multiprocessing.cpu_count())
kwargs["temp_audiofile_path"] = kwargs.get("temp_audiofile_path", output_path.parent.as_posix())
video.write_videofile(output_path.as_posix(), **kwargs)
video.close()
return output_path
|