swap-cli 0.1.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- swap_cli/__init__.py +5 -0
- swap_cli/__main__.py +6 -0
- swap_cli/camera.py +83 -0
- swap_cli/cli.py +1183 -0
- swap_cli/config.py +152 -0
- swap_cli/devices.py +216 -0
- swap_cli/display.py +177 -0
- swap_cli/gui.py +1695 -0
- swap_cli/license.py +93 -0
- swap_cli/runtime.py +273 -0
- swap_cli/rvc_catalog.py +105 -0
- swap_cli/version.py +1 -0
- swap_cli/voice_engines/__init__.py +148 -0
- swap_cli/voice_engines/rvc_converter.py +220 -0
- swap_cli/voice_engines/rvc_engine.py +108 -0
- swap_cli/voice_library.py +141 -0
- swap_cli/voice_ops.py +594 -0
- swap_cli/voice_prereq.py +360 -0
- swap_cli/voice_router.py +153 -0
- swap_cli/voice_track.py +545 -0
- swap_cli/voices/__init__.py +1 -0
- swap_cli-0.1.1.dist-info/METADATA +504 -0
- swap_cli-0.1.1.dist-info/RECORD +26 -0
- swap_cli-0.1.1.dist-info/WHEEL +4 -0
- swap_cli-0.1.1.dist-info/entry_points.txt +2 -0
- swap_cli-0.1.1.dist-info/licenses/LICENSE.md +75 -0
swap_cli/__init__.py
ADDED
swap_cli/__main__.py
ADDED
swap_cli/camera.py
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
"""OpenCV webcam capture exposed as an aiortc VideoStreamTrack."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import asyncio
|
|
6
|
+
import fractions
|
|
7
|
+
import sys
|
|
8
|
+
import time
|
|
9
|
+
from typing import Final
|
|
10
|
+
|
|
11
|
+
import av
|
|
12
|
+
import cv2
|
|
13
|
+
from aiortc import VideoStreamTrack
|
|
14
|
+
|
|
15
|
+
VIDEO_CLOCK_RATE: Final = 90_000 # standard for video tracks
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def _platform_backend() -> int:
|
|
19
|
+
"""Pick the most stable cv2 capture backend for the current OS."""
|
|
20
|
+
if sys.platform == "win32":
|
|
21
|
+
return cv2.CAP_DSHOW
|
|
22
|
+
if sys.platform == "darwin":
|
|
23
|
+
return cv2.CAP_AVFOUNDATION
|
|
24
|
+
return cv2.CAP_V4L2
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class CameraTrack(VideoStreamTrack):
|
|
28
|
+
"""Wraps a `cv2.VideoCapture` device as a WebRTC video track.
|
|
29
|
+
|
|
30
|
+
Designed to be passed to `RealtimeClient.connect(local_track=...)`.
|
|
31
|
+
Frames are pulled lazily as Decart consumes them, paced to the model's fps.
|
|
32
|
+
"""
|
|
33
|
+
|
|
34
|
+
kind = "video"
|
|
35
|
+
|
|
36
|
+
def __init__(self, *, device: int = 0, width: int, height: int, fps: int) -> None:
|
|
37
|
+
super().__init__()
|
|
38
|
+
self._cap = cv2.VideoCapture(device, _platform_backend())
|
|
39
|
+
if not self._cap.isOpened():
|
|
40
|
+
raise RuntimeError(f"Could not open camera device {device}")
|
|
41
|
+
|
|
42
|
+
self._cap.set(cv2.CAP_PROP_FRAME_WIDTH, width)
|
|
43
|
+
self._cap.set(cv2.CAP_PROP_FRAME_HEIGHT, height)
|
|
44
|
+
self._cap.set(cv2.CAP_PROP_FPS, fps)
|
|
45
|
+
|
|
46
|
+
self._width = width
|
|
47
|
+
self._height = height
|
|
48
|
+
self._fps = fps
|
|
49
|
+
self._frame_interval = 1.0 / fps
|
|
50
|
+
self._next_frame_at = time.monotonic()
|
|
51
|
+
self._frame_count = 0
|
|
52
|
+
self._stopped = False
|
|
53
|
+
|
|
54
|
+
async def recv(self) -> av.VideoFrame: # noqa: D401 — aiortc protocol
|
|
55
|
+
# Pace at the model's fps so we don't spam frames faster than Decart
|
|
56
|
+
# negotiates them on the wire.
|
|
57
|
+
now = time.monotonic()
|
|
58
|
+
wait = self._next_frame_at - now
|
|
59
|
+
if wait > 0:
|
|
60
|
+
await asyncio.sleep(wait)
|
|
61
|
+
self._next_frame_at = max(now, self._next_frame_at) + self._frame_interval
|
|
62
|
+
|
|
63
|
+
ok, frame = await asyncio.to_thread(self._cap.read)
|
|
64
|
+
if not ok or frame is None:
|
|
65
|
+
raise RuntimeError("Camera read failed — is another app using the webcam?")
|
|
66
|
+
|
|
67
|
+
# OpenCV is BGR; aiortc/PyAV want a known pixel format.
|
|
68
|
+
rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
|
|
69
|
+
video_frame = av.VideoFrame.from_ndarray(rgb, format="rgb24")
|
|
70
|
+
video_frame.pts = self._frame_count
|
|
71
|
+
video_frame.time_base = fractions.Fraction(1, self._fps)
|
|
72
|
+
self._frame_count += 1
|
|
73
|
+
return video_frame
|
|
74
|
+
|
|
75
|
+
def stop(self) -> None:
|
|
76
|
+
if self._stopped:
|
|
77
|
+
return
|
|
78
|
+
self._stopped = True
|
|
79
|
+
try:
|
|
80
|
+
self._cap.release()
|
|
81
|
+
except Exception:
|
|
82
|
+
pass
|
|
83
|
+
super().stop()
|