129 lines
3.7 KiB
Python
129 lines
3.7 KiB
Python
"""
|
|
TranscodePreset Schema Definition
|
|
|
|
Source of truth for preset data model.
|
|
"""
|
|
|
|
from dataclasses import dataclass, field
|
|
from datetime import datetime
|
|
from typing import List, Optional
|
|
from uuid import UUID
|
|
|
|
|
|
@dataclass
|
|
class TranscodePreset:
|
|
"""
|
|
A reusable transcoding configuration (like Handbrake presets).
|
|
|
|
Presets can be builtin (shipped with the app) or user-created.
|
|
"""
|
|
|
|
id: UUID
|
|
name: str
|
|
description: str = ""
|
|
is_builtin: bool = False
|
|
|
|
# Output container
|
|
container: str = "mp4" # mp4, mkv, webm, mov, avi
|
|
|
|
# Video settings
|
|
video_codec: str = "libx264"
|
|
video_bitrate: Optional[str] = None # "2M", "5000k"
|
|
video_crf: Optional[int] = None # Quality-based (0-51 for x264)
|
|
video_preset: Optional[str] = None # ultrafast...veryslow
|
|
resolution: Optional[str] = None # "1920x1080", "1280x720"
|
|
framerate: Optional[float] = None
|
|
|
|
# Audio settings
|
|
audio_codec: str = "aac"
|
|
audio_bitrate: Optional[str] = None # "128k", "320k"
|
|
audio_channels: Optional[int] = None # 2 for stereo
|
|
audio_samplerate: Optional[int] = None # 44100, 48000
|
|
|
|
# Advanced: extra FFmpeg arguments
|
|
extra_args: List[str] = field(default_factory=list)
|
|
|
|
# Timestamps
|
|
created_at: Optional[datetime] = None
|
|
updated_at: Optional[datetime] = None
|
|
|
|
|
|
BUILTIN_PRESETS = [
|
|
{
|
|
"name": "DaVinci Resolve",
|
|
"description": "MPEG-4 (xvid) + MP3 - Compatible with DaVinci Resolve Free",
|
|
"container": "avi",
|
|
"video_codec": "mpeg4",
|
|
"video_crf": 5,
|
|
"audio_codec": "libmp3lame",
|
|
"audio_bitrate": "320k",
|
|
"audio_samplerate": 48000,
|
|
"extra_args": ["-vtag", "xvid", "-pix_fmt", "yuv420p"],
|
|
},
|
|
{
|
|
"name": "Copy (Trim Only)",
|
|
"description": "Stream copy - No transcoding, fast trimming only",
|
|
"container": "mp4",
|
|
"video_codec": "copy",
|
|
"audio_codec": "copy",
|
|
},
|
|
{
|
|
"name": "Web H.264",
|
|
"description": "H.264 + AAC - General web playback",
|
|
"container": "mp4",
|
|
"video_codec": "libx264",
|
|
"video_crf": 23,
|
|
"video_preset": "medium",
|
|
"audio_codec": "aac",
|
|
"audio_bitrate": "128k",
|
|
},
|
|
{
|
|
"name": "Web H.265",
|
|
"description": "HEVC + AAC - Smaller files, modern browsers",
|
|
"container": "mp4",
|
|
"video_codec": "libx265",
|
|
"video_crf": 28,
|
|
"video_preset": "medium",
|
|
"audio_codec": "aac",
|
|
"audio_bitrate": "128k",
|
|
},
|
|
{
|
|
"name": "DNxHR HQ",
|
|
"description": "DNxHR High Quality - Professional editing",
|
|
"container": "mov",
|
|
"video_codec": "dnxhd",
|
|
"audio_codec": "pcm_s16le",
|
|
"audio_samplerate": 48000,
|
|
"extra_args": ["-profile:v", "dnxhr_hq", "-pix_fmt", "yuv422p"],
|
|
},
|
|
{
|
|
"name": "H.264 NVENC",
|
|
"description": "NVIDIA GPU encoding - Fast H.264",
|
|
"container": "mp4",
|
|
"video_codec": "h264_nvenc",
|
|
"video_bitrate": "10M",
|
|
"audio_codec": "aac",
|
|
"audio_bitrate": "192k",
|
|
"extra_args": ["-preset", "p4", "-rc", "vbr", "-cq", "19"],
|
|
},
|
|
{
|
|
"name": "HEVC NVENC",
|
|
"description": "NVIDIA GPU encoding - HEVC/H.265",
|
|
"container": "mp4",
|
|
"video_codec": "hevc_nvenc",
|
|
"video_bitrate": "8M",
|
|
"audio_codec": "aac",
|
|
"audio_bitrate": "192k",
|
|
"extra_args": ["-preset", "p4", "-rc", "vbr", "-cq", "23"],
|
|
},
|
|
{
|
|
"name": "Archive ProRes",
|
|
"description": "Apple ProRes 422 HQ - Archival quality",
|
|
"container": "mov",
|
|
"video_codec": "prores_ks",
|
|
"audio_codec": "pcm_s16le",
|
|
"audio_samplerate": 48000,
|
|
"extra_args": ["-profile:v", "3"], # ProRes 422 HQ
|
|
},
|
|
]
|