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": "Add Static Image Source",
"streams.edit.static_image": "Edit Static Image Source",
"streams.type.static_image": "Static Image",
"streams.group.video": "Video",
"streams.add.video": "Add Video Source",
"streams.edit.video": "Edit Video Source",
"picture_source.type.video": "Video",
"picture_source.type.video.desc": "Stream frames from video file, URL, or YouTube",
"picture_source.video.url": "Video URL:",
"picture_source.video.url.hint": "Local file path, HTTP URL, or YouTube URL",
"picture_source.video.url.placeholder": "https://example.com/video.mp4",
"picture_source.video.loop": "Loop:",
"picture_source.video.speed": "Playback Speed:",
"picture_source.video.start_time": "Start Time (s):",
"picture_source.video.end_time": "End Time (s):",
"picture_source.video.resolution_limit": "Max Width (px):",
"picture_source.video.resolution_limit.hint": "Downscale video at decode time for performance",
"streams.image_source": "Image Source:",
"streams.image_source.placeholder": "https://example.com/image.jpg or C:\\path\\to\\image.png",
"streams.image_source.hint": "Enter a URL (http/https) or local file path to an image",