videopython 0.33.0__tar.gz → 0.33.1__tar.gz
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.
- {videopython-0.33.0 → videopython-0.33.1}/PKG-INFO +1 -1
- {videopython-0.33.0 → videopython-0.33.1}/pyproject.toml +1 -1
- {videopython-0.33.0 → videopython-0.33.1}/src/videopython/ai/generation/audio.py +13 -8
- {videopython-0.33.0 → videopython-0.33.1}/src/videopython/ai/generation/image.py +6 -1
- {videopython-0.33.0 → videopython-0.33.1}/src/videopython/ai/generation/translation.py +1 -1
- {videopython-0.33.0 → videopython-0.33.1}/src/videopython/ai/generation/video.py +21 -13
- {videopython-0.33.0 → videopython-0.33.1}/src/videopython/ai/understanding/audio.py +9 -0
- {videopython-0.33.0 → videopython-0.33.1}/src/videopython/ai/understanding/image.py +2 -11
- {videopython-0.33.0 → videopython-0.33.1}/src/videopython/ai/understanding/temporal.py +12 -6
- {videopython-0.33.0 → videopython-0.33.1}/.gitignore +0 -0
- {videopython-0.33.0 → videopython-0.33.1}/LICENSE +0 -0
- {videopython-0.33.0 → videopython-0.33.1}/README.md +0 -0
- {videopython-0.33.0 → videopython-0.33.1}/src/videopython/__init__.py +0 -0
- {videopython-0.33.0 → videopython-0.33.1}/src/videopython/ai/__init__.py +0 -0
- {videopython-0.33.0 → videopython-0.33.1}/src/videopython/ai/_device.py +0 -0
- {videopython-0.33.0 → videopython-0.33.1}/src/videopython/ai/dubbing/__init__.py +0 -0
- {videopython-0.33.0 → videopython-0.33.1}/src/videopython/ai/dubbing/config.py +0 -0
- {videopython-0.33.0 → videopython-0.33.1}/src/videopython/ai/dubbing/dubber.py +0 -0
- {videopython-0.33.0 → videopython-0.33.1}/src/videopython/ai/dubbing/expressiveness.py +0 -0
- {videopython-0.33.0 → videopython-0.33.1}/src/videopython/ai/dubbing/loudness.py +0 -0
- {videopython-0.33.0 → videopython-0.33.1}/src/videopython/ai/dubbing/models.py +0 -0
- {videopython-0.33.0 → videopython-0.33.1}/src/videopython/ai/dubbing/pipeline.py +0 -0
- {videopython-0.33.0 → videopython-0.33.1}/src/videopython/ai/dubbing/quality.py +0 -0
- {videopython-0.33.0 → videopython-0.33.1}/src/videopython/ai/dubbing/remux.py +0 -0
- {videopython-0.33.0 → videopython-0.33.1}/src/videopython/ai/dubbing/timing.py +0 -0
- {videopython-0.33.0 → videopython-0.33.1}/src/videopython/ai/dubbing/voice_sample.py +0 -0
- {videopython-0.33.0 → videopython-0.33.1}/src/videopython/ai/generation/__init__.py +0 -0
- {videopython-0.33.0 → videopython-0.33.1}/src/videopython/ai/generation/qwen3.py +0 -0
- {videopython-0.33.0 → videopython-0.33.1}/src/videopython/ai/transforms.py +0 -0
- {videopython-0.33.0 → videopython-0.33.1}/src/videopython/ai/understanding/__init__.py +0 -0
- {videopython-0.33.0 → videopython-0.33.1}/src/videopython/ai/understanding/faces.py +0 -0
- {videopython-0.33.0 → videopython-0.33.1}/src/videopython/ai/understanding/separation.py +0 -0
- {videopython-0.33.0 → videopython-0.33.1}/src/videopython/ai/video_analysis/__init__.py +0 -0
- {videopython-0.33.0 → videopython-0.33.1}/src/videopython/ai/video_analysis/analyzer.py +0 -0
- {videopython-0.33.0 → videopython-0.33.1}/src/videopython/ai/video_analysis/models.py +0 -0
- {videopython-0.33.0 → videopython-0.33.1}/src/videopython/ai/video_analysis/sampling.py +0 -0
- {videopython-0.33.0 → videopython-0.33.1}/src/videopython/ai/video_analysis/stages.py +0 -0
- {videopython-0.33.0 → videopython-0.33.1}/src/videopython/audio/__init__.py +0 -0
- {videopython-0.33.0 → videopython-0.33.1}/src/videopython/audio/analysis.py +0 -0
- {videopython-0.33.0 → videopython-0.33.1}/src/videopython/audio/audio.py +0 -0
- {videopython-0.33.0 → videopython-0.33.1}/src/videopython/base/__init__.py +0 -0
- {videopython-0.33.0 → videopython-0.33.1}/src/videopython/base/_dimensions.py +0 -0
- {videopython-0.33.0 → videopython-0.33.1}/src/videopython/base/_ffmpeg.py +0 -0
- {videopython-0.33.0 → videopython-0.33.1}/src/videopython/base/_video_io.py +0 -0
- {videopython-0.33.0 → videopython-0.33.1}/src/videopython/base/description.py +0 -0
- {videopython-0.33.0 → videopython-0.33.1}/src/videopython/base/exceptions.py +0 -0
- {videopython-0.33.0 → videopython-0.33.1}/src/videopython/base/image_text.py +0 -0
- {videopython-0.33.0 → videopython-0.33.1}/src/videopython/base/transcription.py +0 -0
- {videopython-0.33.0 → videopython-0.33.1}/src/videopython/base/video.py +0 -0
- {videopython-0.33.0 → videopython-0.33.1}/src/videopython/editing/__init__.py +0 -0
- {videopython-0.33.0 → videopython-0.33.1}/src/videopython/editing/effects.py +0 -0
- {videopython-0.33.0 → videopython-0.33.1}/src/videopython/editing/operation.py +0 -0
- {videopython-0.33.0 → videopython-0.33.1}/src/videopython/editing/streaming.py +0 -0
- {videopython-0.33.0 → videopython-0.33.1}/src/videopython/editing/transcription_overlay.py +0 -0
- {videopython-0.33.0 → videopython-0.33.1}/src/videopython/editing/transforms.py +0 -0
- {videopython-0.33.0 → videopython-0.33.1}/src/videopython/editing/video_edit.py +0 -0
- {videopython-0.33.0 → videopython-0.33.1}/src/videopython/py.typed +0 -0
|
@@ -32,7 +32,7 @@ class TextToSpeech:
|
|
|
32
32
|
self.language = language
|
|
33
33
|
self._model: Any = None
|
|
34
34
|
|
|
35
|
-
def
|
|
35
|
+
def _init_local(self) -> None:
|
|
36
36
|
from chatterbox.mtl_tts import ChatterboxMultilingualTTS # type: ignore[import-untyped]
|
|
37
37
|
|
|
38
38
|
requested_device = self.device
|
|
@@ -83,7 +83,7 @@ class TextToSpeech:
|
|
|
83
83
|
import numpy as np
|
|
84
84
|
|
|
85
85
|
if self._model is None:
|
|
86
|
-
self.
|
|
86
|
+
self._init_local()
|
|
87
87
|
|
|
88
88
|
speaker_wav_path: Path | None = None
|
|
89
89
|
cleanup_path = False
|
|
@@ -149,7 +149,6 @@ class TextToMusic:
|
|
|
149
149
|
self.device = device
|
|
150
150
|
self._processor: Any = None
|
|
151
151
|
self._model: Any = None
|
|
152
|
-
self._device: str | None = None
|
|
153
152
|
|
|
154
153
|
def _init_local(self) -> None:
|
|
155
154
|
"""Initialize local MusicGen model."""
|
|
@@ -160,17 +159,17 @@ class TextToMusic:
|
|
|
160
159
|
os.environ["PYTORCH_ENABLE_MPS_FALLBACK"] = "1"
|
|
161
160
|
|
|
162
161
|
requested_device = self.device
|
|
163
|
-
|
|
162
|
+
device = select_device(self.device, mps_allowed=True)
|
|
164
163
|
|
|
165
164
|
model_name = "facebook/musicgen-small"
|
|
166
165
|
self._processor = AutoProcessor.from_pretrained(model_name)
|
|
167
166
|
self._model = MusicgenForConditionalGeneration.from_pretrained(model_name)
|
|
168
|
-
self._model.to(
|
|
169
|
-
self.device =
|
|
167
|
+
self._model.to(device)
|
|
168
|
+
self.device = device
|
|
170
169
|
log_device_initialization(
|
|
171
170
|
"TextToMusic",
|
|
172
171
|
requested_device=requested_device,
|
|
173
|
-
resolved_device=
|
|
172
|
+
resolved_device=device,
|
|
174
173
|
)
|
|
175
174
|
|
|
176
175
|
def generate_audio(self, text: str, max_new_tokens: int = 256) -> Audio:
|
|
@@ -179,7 +178,7 @@ class TextToMusic:
|
|
|
179
178
|
self._init_local()
|
|
180
179
|
|
|
181
180
|
inputs = self._processor(text=[text], padding=True, return_tensors="pt")
|
|
182
|
-
inputs = {k: v.to(self.
|
|
181
|
+
inputs = {k: v.to(self.device) if hasattr(v, "to") else v for k, v in inputs.items()}
|
|
183
182
|
audio_values = self._model.generate(**inputs, max_new_tokens=max_new_tokens)
|
|
184
183
|
sampling_rate = self._model.config.audio_encoder.sampling_rate
|
|
185
184
|
|
|
@@ -193,3 +192,9 @@ class TextToMusic:
|
|
|
193
192
|
frame_count=len(audio_data),
|
|
194
193
|
)
|
|
195
194
|
return Audio(audio_data, metadata)
|
|
195
|
+
|
|
196
|
+
def unload(self) -> None:
|
|
197
|
+
"""Release the MusicGen model so the next generate_audio() re-initializes."""
|
|
198
|
+
self._model = None
|
|
199
|
+
self._processor = None
|
|
200
|
+
release_device_memory(self.device)
|
|
@@ -6,7 +6,7 @@ from typing import Any
|
|
|
6
6
|
|
|
7
7
|
from PIL import Image
|
|
8
8
|
|
|
9
|
-
from videopython.ai._device import log_device_initialization, select_device
|
|
9
|
+
from videopython.ai._device import log_device_initialization, release_device_memory, select_device
|
|
10
10
|
|
|
11
11
|
|
|
12
12
|
class TextToImage:
|
|
@@ -49,3 +49,8 @@ class TextToImage:
|
|
|
49
49
|
if self._pipeline is None:
|
|
50
50
|
self._init_local()
|
|
51
51
|
return self._pipeline(prompt=prompt).images[0]
|
|
52
|
+
|
|
53
|
+
def unload(self) -> None:
|
|
54
|
+
"""Release the diffusion pipeline so the next generate_image() re-initializes."""
|
|
55
|
+
self._pipeline = None
|
|
56
|
+
release_device_memory(self.device)
|
|
@@ -181,7 +181,7 @@ class MarianTranslator:
|
|
|
181
181
|
self._model = MarianMTModel.from_pretrained(model_name).to(device)
|
|
182
182
|
self.device = device
|
|
183
183
|
log_device_initialization(
|
|
184
|
-
"
|
|
184
|
+
"MarianTranslator",
|
|
185
185
|
requested_device=requested_device,
|
|
186
186
|
resolved_device=device,
|
|
187
187
|
)
|
|
@@ -6,7 +6,7 @@ from typing import TYPE_CHECKING, Any
|
|
|
6
6
|
|
|
7
7
|
import numpy as np
|
|
8
8
|
|
|
9
|
-
from videopython.ai._device import log_device_initialization, select_device
|
|
9
|
+
from videopython.ai._device import log_device_initialization, release_device_memory, select_device
|
|
10
10
|
from videopython.base.video import Video
|
|
11
11
|
|
|
12
12
|
if TYPE_CHECKING:
|
|
@@ -29,22 +29,21 @@ class TextToVideo:
|
|
|
29
29
|
def __init__(self, device: str | None = None):
|
|
30
30
|
self.device = device
|
|
31
31
|
self._pipeline: Any = None
|
|
32
|
-
self._device: str | None = None
|
|
33
32
|
|
|
34
33
|
def _init_local(self) -> None:
|
|
35
34
|
from diffusers import CogVideoXPipeline
|
|
36
35
|
|
|
37
36
|
requested_device = self.device
|
|
38
|
-
|
|
37
|
+
device, dtype = _get_torch_device_and_dtype(self.device)
|
|
39
38
|
|
|
40
39
|
model_name = "THUDM/CogVideoX1.5-5B"
|
|
41
40
|
self._pipeline = CogVideoXPipeline.from_pretrained(model_name, torch_dtype=dtype)
|
|
42
|
-
self._pipeline.to(
|
|
43
|
-
self.device =
|
|
41
|
+
self._pipeline.to(device)
|
|
42
|
+
self.device = device
|
|
44
43
|
log_device_initialization(
|
|
45
44
|
"TextToVideo",
|
|
46
45
|
requested_device=requested_device,
|
|
47
|
-
resolved_device=
|
|
46
|
+
resolved_device=device,
|
|
48
47
|
)
|
|
49
48
|
|
|
50
49
|
def generate_video(
|
|
@@ -65,11 +64,16 @@ class TextToVideo:
|
|
|
65
64
|
num_inference_steps=num_steps,
|
|
66
65
|
num_frames=num_frames,
|
|
67
66
|
guidance_scale=guidance_scale,
|
|
68
|
-
generator=torch.Generator(device=self.
|
|
67
|
+
generator=torch.Generator(device=self.device).manual_seed(42),
|
|
69
68
|
).frames[0]
|
|
70
69
|
video_frames = np.asarray(video_frames, dtype=np.uint8)
|
|
71
70
|
return Video.from_frames(video_frames, fps=16.0)
|
|
72
71
|
|
|
72
|
+
def unload(self) -> None:
|
|
73
|
+
"""Release the diffusion pipeline so the next generate_video() re-initializes."""
|
|
74
|
+
self._pipeline = None
|
|
75
|
+
release_device_memory(self.device)
|
|
76
|
+
|
|
73
77
|
|
|
74
78
|
class ImageToVideo:
|
|
75
79
|
"""Generates videos from static images using local video diffusion."""
|
|
@@ -77,22 +81,21 @@ class ImageToVideo:
|
|
|
77
81
|
def __init__(self, device: str | None = None):
|
|
78
82
|
self.device = device
|
|
79
83
|
self._pipeline: Any = None
|
|
80
|
-
self._device: str | None = None
|
|
81
84
|
|
|
82
85
|
def _init_local(self) -> None:
|
|
83
86
|
from diffusers import CogVideoXImageToVideoPipeline
|
|
84
87
|
|
|
85
88
|
requested_device = self.device
|
|
86
|
-
|
|
89
|
+
device, dtype = _get_torch_device_and_dtype(self.device)
|
|
87
90
|
|
|
88
91
|
model_name = "THUDM/CogVideoX1.5-5B-I2V"
|
|
89
92
|
self._pipeline = CogVideoXImageToVideoPipeline.from_pretrained(model_name, torch_dtype=dtype)
|
|
90
|
-
self._pipeline.to(
|
|
91
|
-
self.device =
|
|
93
|
+
self._pipeline.to(device)
|
|
94
|
+
self.device = device
|
|
92
95
|
log_device_initialization(
|
|
93
96
|
"ImageToVideo",
|
|
94
97
|
requested_device=requested_device,
|
|
95
|
-
resolved_device=
|
|
98
|
+
resolved_device=device,
|
|
96
99
|
)
|
|
97
100
|
|
|
98
101
|
def generate_video(
|
|
@@ -115,7 +118,12 @@ class ImageToVideo:
|
|
|
115
118
|
num_inference_steps=num_steps,
|
|
116
119
|
num_frames=num_frames,
|
|
117
120
|
guidance_scale=guidance_scale,
|
|
118
|
-
generator=torch.Generator(device=self.
|
|
121
|
+
generator=torch.Generator(device=self.device).manual_seed(42),
|
|
119
122
|
).frames[0]
|
|
120
123
|
video_frames = np.asarray(video_frames, dtype=np.uint8)
|
|
121
124
|
return Video.from_frames(video_frames, fps=16.0)
|
|
125
|
+
|
|
126
|
+
def unload(self) -> None:
|
|
127
|
+
"""Release the diffusion pipeline so the next generate_video() re-initializes."""
|
|
128
|
+
self._pipeline = None
|
|
129
|
+
release_device_memory(self.device)
|
|
@@ -520,6 +520,15 @@ class AudioClassifier:
|
|
|
520
520
|
|
|
521
521
|
self._labels = [self._model.config.id2label[i] for i in range(len(self._model.config.id2label))]
|
|
522
522
|
|
|
523
|
+
def unload(self) -> None:
|
|
524
|
+
"""Release the AST model so the next classify() re-initializes.
|
|
525
|
+
|
|
526
|
+
Used by low-memory dubbing to free VRAM between pipeline stages.
|
|
527
|
+
"""
|
|
528
|
+
self._model = None
|
|
529
|
+
self._processor = None
|
|
530
|
+
release_device_memory(self.device)
|
|
531
|
+
|
|
523
532
|
def _merge_events(self, events: list[AudioEvent], gap_threshold: float = 0.5) -> list[AudioEvent]:
|
|
524
533
|
"""Merge consecutive events of the same class."""
|
|
525
534
|
if not events:
|
|
@@ -11,7 +11,7 @@ from typing import Any, Literal
|
|
|
11
11
|
import numpy as np
|
|
12
12
|
from PIL import Image
|
|
13
13
|
|
|
14
|
-
from videopython.ai._device import log_device_initialization, select_device
|
|
14
|
+
from videopython.ai._device import log_device_initialization, release_device_memory, select_device
|
|
15
15
|
from videopython.base.description import SceneDescription
|
|
16
16
|
|
|
17
17
|
logger = logging.getLogger(__name__)
|
|
@@ -190,16 +190,7 @@ class SceneVLM:
|
|
|
190
190
|
"""
|
|
191
191
|
self._model = None
|
|
192
192
|
self._processor = None
|
|
193
|
-
|
|
194
|
-
import gc
|
|
195
|
-
|
|
196
|
-
import torch
|
|
197
|
-
|
|
198
|
-
gc.collect()
|
|
199
|
-
if torch.cuda.is_available():
|
|
200
|
-
torch.cuda.empty_cache()
|
|
201
|
-
except ImportError:
|
|
202
|
-
pass
|
|
193
|
+
release_device_memory(self.device)
|
|
203
194
|
|
|
204
195
|
def _downscale_image(self, img: Image.Image) -> Image.Image:
|
|
205
196
|
"""Downscale image to fit within max_image_pixels budget, preserving aspect ratio."""
|
|
@@ -9,7 +9,7 @@ from __future__ import annotations
|
|
|
9
9
|
from pathlib import Path
|
|
10
10
|
from typing import TYPE_CHECKING, Any
|
|
11
11
|
|
|
12
|
-
from videopython.ai._device import log_device_initialization, select_device
|
|
12
|
+
from videopython.ai._device import log_device_initialization, release_device_memory, select_device
|
|
13
13
|
from videopython.base.description import SceneBoundary
|
|
14
14
|
|
|
15
15
|
if TYPE_CHECKING:
|
|
@@ -56,26 +56,32 @@ class SemanticSceneDetector:
|
|
|
56
56
|
|
|
57
57
|
self.threshold = threshold
|
|
58
58
|
self.min_scene_length = min_scene_length
|
|
59
|
-
self.
|
|
59
|
+
self.device: str | None = device
|
|
60
60
|
self._model: Any = None
|
|
61
61
|
|
|
62
|
-
def
|
|
62
|
+
def _init_local(self) -> None:
|
|
63
63
|
"""Load the TransNetV2 model with pretrained weights."""
|
|
64
64
|
if self._model is not None:
|
|
65
65
|
return
|
|
66
66
|
|
|
67
67
|
from transnetv2_pytorch import TransNetV2
|
|
68
68
|
|
|
69
|
-
requested_device = self.
|
|
70
|
-
device = select_device(self.
|
|
69
|
+
requested_device = self.device
|
|
70
|
+
device = select_device(self.device, mps_allowed=True)
|
|
71
71
|
log_device_initialization(
|
|
72
72
|
"SemanticSceneDetector",
|
|
73
73
|
requested_device=requested_device,
|
|
74
74
|
resolved_device=device,
|
|
75
75
|
)
|
|
76
|
+
self.device = device
|
|
76
77
|
self._model = TransNetV2(device=device)
|
|
77
78
|
self._model.eval()
|
|
78
79
|
|
|
80
|
+
def unload(self) -> None:
|
|
81
|
+
"""Release the TransNetV2 model so the next call re-initializes."""
|
|
82
|
+
self._model = None
|
|
83
|
+
release_device_memory(self.device)
|
|
84
|
+
|
|
79
85
|
def detect(self, video: Video) -> list[SceneBoundary]:
|
|
80
86
|
"""Detect scenes in a video using ML-based boundary detection.
|
|
81
87
|
|
|
@@ -114,7 +120,7 @@ class SemanticSceneDetector:
|
|
|
114
120
|
Returns:
|
|
115
121
|
List of SceneBoundary objects representing detected scenes.
|
|
116
122
|
"""
|
|
117
|
-
self.
|
|
123
|
+
self._init_local()
|
|
118
124
|
|
|
119
125
|
# Use TransNetV2's detect_scenes which handles everything internally
|
|
120
126
|
raw_scenes = self._model.detect_scenes(str(path), threshold=self.threshold)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|