Skip to content

zimscraperlib.video

Modules:

Classes:

Functions:

Config

Config(**kwargs: Any)

Bases: dict[str, str | None]

Methods:

  • build_from

    build a Config easily via shortcut params

  • to_ffmpeg_args

    Convert the options dict to list of ffmpeg arguments

  • update_from

    Updates Config object based on shortcut params as given in build_from()

Attributes:

Source code in src/zimscraperlib/video/config.py
21
22
23
24
def __init__(self, **kwargs: Any):
    super().__init__(self, **type(self).defaults)
    self.update(self.options)
    self.update(kwargs)

VERSION class-attribute instance-attribute

VERSION = 1

audio_codec property writable

audio_codec

audio_sampling_rate property writable

audio_sampling_rate

buffersize property writable

buffersize

defaults class-attribute

defaults: dict[str, str | None] = {
    "-max_muxing_queue_size": "9999"
}

ext class-attribute instance-attribute

ext = 'dat'

mapping class-attribute

mapping: dict[str, str] = {
    "video_codec": "-codec:v",
    "audio_codec": "-codec:a",
    "max_video_bitrate": "-maxrate",
    "min_video_bitrate": "-minrate",
    "target_video_bitrate": "-b:v",
    "buffersize": "-bufsize",
    "audio_sampling_rate": "-ar",
    "target_audio_bitrate": "-b:a",
}

max_video_bitrate property writable

max_video_bitrate

mimetype class-attribute instance-attribute

mimetype = 'application/data'

min_video_bitrate property writable

min_video_bitrate

options class-attribute

options: dict[str, str | None] = {}

quantizer_scale_range property writable

quantizer_scale_range

target_audio_bitrate property writable

target_audio_bitrate

target_video_bitrate property writable

target_video_bitrate

video_codec property writable

video_codec

video_scale property writable

video_scale: str | None

build_from classmethod

build_from(**params: Any)

build a Config easily via shortcut params

video_codec: codec for output audio stream. more info https://ffmpeg.org/ffmpeg-codecs.html#Video-Encoders values: h264 | libvpx | libx264 | libx265 | xxx audio_codec: codec for output audio stream. more info https://ffmpeg.org/ffmpeg-codecs.html#Audio-Encoders values: aac | mp3 | flac | opus | libvorbis | xxx max_video_bitrate: maximum size per second for video stream values: 128k | 1m min_video_bitrate: minimum size per second for video stream values: 128k | 1m target_video_bitrate: tentative size per second for video stream values: 384k | 1m target_audio_bitrate: tentative size per second for audio stream values: 48k | 128k buffersize: decoder buffer size values: 1000k | 1m audio_sampling_rate: number of audio samples per second values: 44100 | 48000 quantizer_scale_range: tuple of min / max values of video quantizer scale (VBR) values: (21, 35) | (68, 97) | (x, y) video_scale: video frame scale. more info - https://trac.ffmpeg.org/wiki/Scaling values: 480:320 | 320:240 | width:height

Source code in src/zimscraperlib/video/config.py
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
@classmethod
def build_from(cls, **params: Any):
    """build a Config easily via shortcut params

    video_codec: codec for output audio stream. more info
    https://ffmpeg.org/ffmpeg-codecs.html#Video-Encoders
        values: h264 | libvpx | libx264 | libx265 | xxx
    audio_codec: codec for output audio stream. more info
    https://ffmpeg.org/ffmpeg-codecs.html#Audio-Encoders
        values: aac | mp3 | flac | opus | libvorbis | xxx
    max_video_bitrate: maximum size per second for video stream
        values: 128k | 1m
    min_video_bitrate: minimum size per second for video stream
        values: 128k | 1m
    target_video_bitrate: tentative size per second for video stream
        values: 384k | 1m
    target_audio_bitrate: tentative size per second for audio stream
        values: 48k | 128k
    buffersize: decoder buffer size
        values: 1000k | 1m
    audio_sampling_rate: number of audio samples per second
        values: 44100 | 48000
    quantizer_scale_range: tuple of min / max values of video quantizer scale (VBR)
        values: (21, 35) | (68, 97) | (x, y)
    video_scale: video frame scale. more info - https://trac.ffmpeg.org/wiki/Scaling
        values: 480:320 | 320:240 | width:height
    """
    config = cls()
    config.update_from(**params)
    return config

to_ffmpeg_args

to_ffmpeg_args() -> list[str]

Convert the options dict to list of ffmpeg arguments

Source code in src/zimscraperlib/video/config.py
32
33
34
35
36
37
38
39
40
41
42
43
def to_ffmpeg_args(self) -> list[str]:
    """Convert the options dict to list of ffmpeg arguments"""

    args: list[str] = []
    for k, v in self.items():
        if v:
            args += [k, v]
        else:
            args += [
                k
            ]  # put only k in cases it's not followed by a value (boolean flag)
    return args

update_from

update_from(**kwargs: Any)

Updates Config object based on shortcut params as given in build_from()

Source code in src/zimscraperlib/video/config.py
26
27
28
29
30
def update_from(self, **kwargs: Any):
    """Updates Config object based on shortcut params as given in build_from()"""

    for key, value in kwargs.items():
        setattr(self, key, value)

get_media_info

get_media_info(src_path: Path)

dict of file's details from ffprobe

codecs: list of codecs in use duration: file duration in seconds bitrate: file's main bitrate

Source code in src/zimscraperlib/video/probing.py
 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
def get_media_info(src_path: pathlib.Path):
    """dict of file's details from ffprobe

    codecs: list of codecs in use
    duration: file duration in seconds
    bitrate: file's main bitrate"""

    args = [
        "/usr/bin/env",
        "ffprobe",
        "-i",
        f"file:{src_path}",
        "-show_entries",
        "stream=codec_name",
        "-show_entries",
        "format=duration,bit_rate",
        "-v",
        "quiet",
        "-of",
        "csv",
    ]
    ffprobe = subprocess.run(
        args,
        capture_output=True,
        text=True,
        check=False,
    )
    result = ffprobe.stdout.strip().split("\n")
    streams = result[:-1]
    codecs = [stream.split(",")[-1] for stream in streams]
    format_info = result[-1].split(",")[1:]
    return {
        "codecs": codecs,
        "duration": int(format_info[0].split(".")[0]),
        "bitrate": int(format_info[1]),
    }

reencode

reencode(
    src_path: Path,
    dst_path: Path,
    ffmpeg_args: list[str],
    threads: int | None = 1,
    *,
    delete_src: bool = False,
    failsafe: bool = True,
    existing_tmp_path: Path | None = None,
) -> tuple[bool, CompletedProcess[str]]

Runs ffmpeg with given ffmpeg_args

Arguments - src_path - Path to source file dst_path - Path to destination file ffmpeg_args - A list of ffmpeg arguments threads - Number of encoding threads used by ffmpeg delete_src - Delete source file after convertion failsafe - Run in failsafe mode

Source code in src/zimscraperlib/video/encoding.py
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
75
76
77
78
79
80
81
82
def reencode(
    src_path: pathlib.Path,
    dst_path: pathlib.Path,
    ffmpeg_args: list[str],
    threads: int | None = 1,
    *,
    delete_src: bool = False,
    failsafe: bool = True,
    existing_tmp_path: pathlib.Path | None = None,
) -> tuple[bool, subprocess.CompletedProcess[str]]:
    """Runs ffmpeg with given ffmpeg_args

    Arguments -
        src_path - Path to source file
        dst_path - Path to destination file
        ffmpeg_args - A list of ffmpeg arguments
        threads - Number of encoding threads used by ffmpeg
        delete_src - Delete source file after convertion
        failsafe - Run in failsafe mode
    """

    with path_from(existing_tmp_path or tempfile.TemporaryDirectory()) as tmp_dir:
        tmp_path = pathlib.Path(tmp_dir).joinpath(f"video.tmp{dst_path.suffix}")
        args = _build_ffmpeg_args(
            src_path=src_path,
            tmp_path=tmp_path,
            ffmpeg_args=ffmpeg_args,
            threads=threads,
        )
        logger.debug(
            f"Encode {src_path} -> {dst_path} video format = {dst_path.suffix}"
        )
        logger.debug(nicer_args_join(args))
        ffmpeg = subprocess.run(
            args,
            stderr=subprocess.STDOUT,
            stdout=subprocess.PIPE,
            text=True,
            check=False,
        )
        if not failsafe:
            ffmpeg.check_returncode()
        if ffmpeg.returncode == 0:
            if delete_src:
                src_path.unlink()
            shutil.copy(tmp_path, dst_path)
        return ffmpeg.returncode == 0, ffmpeg