1 2 3 4 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 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 83 84 85 86 87 88 89 90 91 92 93 94 95
|
from __future__ import annotations
from dataclasses import dataclass
from typing import TypedDict
import av
from av.codec import Codec
class DictContainer(TypedDict, total=False):
max_videos: int | None
max_audios: int | None
max_subtitles: int | None
samplerate: list[int] | None
@dataclass(slots=True)
class Container:
allow_image: bool
vcodecs: set[str]
acodecs: set[str]
scodecs: set[str]
default_vid: str
default_aud: str
default_sub: str
max_videos: int | None = None
max_audios: int | None = None
max_subtitles: int | None = None
samplerate: list[int] | None = None # Any samplerate is allowed
containers: dict[str, DictContainer] = {
"aac": {"max_audios": 1},
"adts": {"max_audios": 1},
"ass": {"max_subtitles": 1},
"ssa": {"max_subtitles": 1},
"apng": {"max_videos": 1},
"gif": {"max_videos": 1},
"wav": {"max_audios": 1},
"ast": {"max_audios": 1},
"mp3": {"max_audios": 1},
"flac": {"max_audios": 1},
"srt": {"max_subtitles": 1},
"vtt": {"max_subtitles": 1},
"swf": {"samplerate": [44100, 22050, 11025]},
}
def codec_type(x: str) -> str:
if x in {"vp9", "vp8", "h264", "hevc", "av1", "gif", "apng"}:
return "video"
if x in {"aac", "flac", "mp3"}:
return "audio"
if x in {"ass", "ssa", "srt"}:
return "subtitle"
try:
return Codec(x, "w").type
except Exception:
return ""
def container_constructor(ext: str) -> Container:
with av.open(f".{ext}", "w") as container:
codecs = container.supported_codecs
if ext == "webm":
vdefault = "vp9"
else:
vdefault = container.default_video_codec
adefault = container.default_audio_codec
sdefault = container.default_subtitle_codec
if sdefault == "none" and ext == "mp4":
sdefault = "srt"
vcodecs = set()
acodecs = set()
scodecs = set()
for codec in codecs:
if ext == "wav" and codec == "aac":
continue
kind = codec_type(codec)
if kind == "video":
vcodecs.add(codec)
if kind == "audio":
acodecs.add(codec)
if kind == "subtitle":
scodecs.add(codec)
allow_image = ext in {"mp4", "mkv"}
kwargs = containers[ext] if ext in containers else {}
return Container(
allow_image, vcodecs, acodecs, scodecs, vdefault, adefault, sdefault, **kwargs
)
|