Add video picture source: file, URL, YouTube, sync clock, trim, test preview

Backend:
- VideoCaptureSource dataclass with url, loop, playback_speed, start/end_time,
  resolution_limit, clock_id, target_fps fields
- VideoCaptureStream: OpenCV decode thread with frame-accurate sync clock seeking,
  loop, trim range, resolution downscale at decode time
- YouTube URL resolution via yt-dlp (auto-detects youtube.com, youtu.be, shorts)
- Thumbnail extraction from first frame (GET /picture-sources/{id}/thumbnail)
- Video test WS preview: streams JPEG frames with elapsed/frame_count metadata
- Run video_stream.start() in executor to avoid blocking event loop during
  yt-dlp resolution
- Full CRUD via existing picture source API (stream_type: "video")
- Wired into LiveStreamManager for target streaming

Frontend:
- Video icon (film) in picture source type map and graph node subtypes
- Video tree nav node in Sources tab with CardSection
- Video fields in stream add/edit modal: URL, loop toggle, playback speed slider,
  target FPS, start/end trim times, resolution limit
- Video card rendering with URL, FPS, loop, speed badges
- Clone data support for video sources
- i18n keys for video source in en/ru/zh

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-03-15 23:48:43 +03:00
parent 0bbaf81e26
commit 0bb4d7c3aa
14 changed files with 826 additions and 23 deletions

View File

@@ -553,6 +553,20 @@
"streams.add.static_image": "Добавить статическое изображение (источник)",
"streams.edit.static_image": "Редактировать статическое изображение (источник)",
"streams.type.static_image": "Статическое изображение",
"streams.group.video": "Видео",
"streams.add.video": "Добавить видеоисточник",
"streams.edit.video": "Редактировать видеоисточник",
"picture_source.type.video": "Видео",
"picture_source.type.video.desc": "Потоковые кадры из видеофайла, URL или YouTube",
"picture_source.video.url": "URL видео:",
"picture_source.video.url.hint": "Локальный файл, HTTP URL или YouTube URL",
"picture_source.video.url.placeholder": "https://example.com/video.mp4",
"picture_source.video.loop": "Зацикливание:",
"picture_source.video.speed": "Скорость воспроизведения:",
"picture_source.video.start_time": "Время начала (с):",
"picture_source.video.end_time": "Время окончания (с):",
"picture_source.video.resolution_limit": "Макс. ширина (px):",
"picture_source.video.resolution_limit.hint": "Уменьшение видео при декодировании для производительности",
"streams.image_source": "Источник изображения:",
"streams.image_source.placeholder": "https://example.com/image.jpg или C:\\path\\to\\image.png",
"streams.image_source.hint": "Введите URL (http/https) или локальный путь к изображению",