videopython 0.44.1__tar.gz → 0.45.0__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.44.1 → videopython-0.45.0}/PKG-INFO +1 -1
- {videopython-0.44.1 → videopython-0.45.0}/pyproject.toml +1 -1
- {videopython-0.44.1 → videopython-0.45.0}/src/videopython/base/exceptions.py +1 -1
- {videopython-0.44.1 → videopython-0.45.0}/src/videopython/editing/streaming.py +7 -7
- {videopython-0.44.1 → videopython-0.45.0}/src/videopython/editing/video_edit.py +8 -8
- {videopython-0.44.1 → videopython-0.45.0}/.gitignore +0 -0
- {videopython-0.44.1 → videopython-0.45.0}/LICENSE +0 -0
- {videopython-0.44.1 → videopython-0.45.0}/README.md +0 -0
- {videopython-0.44.1 → videopython-0.45.0}/src/videopython/__init__.py +0 -0
- {videopython-0.44.1 → videopython-0.45.0}/src/videopython/ai/__init__.py +0 -0
- {videopython-0.44.1 → videopython-0.45.0}/src/videopython/ai/_device.py +0 -0
- {videopython-0.44.1 → videopython-0.45.0}/src/videopython/ai/_optional.py +0 -0
- {videopython-0.44.1 → videopython-0.45.0}/src/videopython/ai/_predictor.py +0 -0
- {videopython-0.44.1 → videopython-0.45.0}/src/videopython/ai/_revisions.py +0 -0
- {videopython-0.44.1 → videopython-0.45.0}/src/videopython/ai/dubbing/__init__.py +0 -0
- {videopython-0.44.1 → videopython-0.45.0}/src/videopython/ai/dubbing/config.py +0 -0
- {videopython-0.44.1 → videopython-0.45.0}/src/videopython/ai/dubbing/dubber.py +0 -0
- {videopython-0.44.1 → videopython-0.45.0}/src/videopython/ai/dubbing/expressiveness.py +0 -0
- {videopython-0.44.1 → videopython-0.45.0}/src/videopython/ai/dubbing/loudness.py +0 -0
- {videopython-0.44.1 → videopython-0.45.0}/src/videopython/ai/dubbing/models.py +0 -0
- {videopython-0.44.1 → videopython-0.45.0}/src/videopython/ai/dubbing/pipeline.py +0 -0
- {videopython-0.44.1 → videopython-0.45.0}/src/videopython/ai/dubbing/quality.py +0 -0
- {videopython-0.44.1 → videopython-0.45.0}/src/videopython/ai/dubbing/remux.py +0 -0
- {videopython-0.44.1 → videopython-0.45.0}/src/videopython/ai/dubbing/timing.py +0 -0
- {videopython-0.44.1 → videopython-0.45.0}/src/videopython/ai/dubbing/voice_sample.py +0 -0
- {videopython-0.44.1 → videopython-0.45.0}/src/videopython/ai/effects.py +0 -0
- {videopython-0.44.1 → videopython-0.45.0}/src/videopython/ai/generation/__init__.py +0 -0
- {videopython-0.44.1 → videopython-0.45.0}/src/videopython/ai/generation/_tts_backend.py +0 -0
- {videopython-0.44.1 → videopython-0.45.0}/src/videopython/ai/generation/audio.py +0 -0
- {videopython-0.44.1 → videopython-0.45.0}/src/videopython/ai/generation/image.py +0 -0
- {videopython-0.44.1 → videopython-0.45.0}/src/videopython/ai/generation/qwen3.py +0 -0
- {videopython-0.44.1 → videopython-0.45.0}/src/videopython/ai/generation/translation.py +0 -0
- {videopython-0.44.1 → videopython-0.45.0}/src/videopython/ai/generation/video.py +0 -0
- {videopython-0.44.1 → videopython-0.45.0}/src/videopython/ai/transforms.py +0 -0
- {videopython-0.44.1 → videopython-0.45.0}/src/videopython/ai/understanding/__init__.py +0 -0
- {videopython-0.44.1 → videopython-0.45.0}/src/videopython/ai/understanding/audio.py +0 -0
- {videopython-0.44.1 → videopython-0.45.0}/src/videopython/ai/understanding/faces.py +0 -0
- {videopython-0.44.1 → videopython-0.45.0}/src/videopython/ai/understanding/image.py +0 -0
- {videopython-0.44.1 → videopython-0.45.0}/src/videopython/ai/understanding/objects.py +0 -0
- {videopython-0.44.1 → videopython-0.45.0}/src/videopython/ai/understanding/separation.py +0 -0
- {videopython-0.44.1 → videopython-0.45.0}/src/videopython/ai/understanding/temporal.py +0 -0
- {videopython-0.44.1 → videopython-0.45.0}/src/videopython/ai/video_analysis/__init__.py +0 -0
- {videopython-0.44.1 → videopython-0.45.0}/src/videopython/ai/video_analysis/analyzer.py +0 -0
- {videopython-0.44.1 → videopython-0.45.0}/src/videopython/ai/video_analysis/models.py +0 -0
- {videopython-0.44.1 → videopython-0.45.0}/src/videopython/ai/video_analysis/sampling.py +0 -0
- {videopython-0.44.1 → videopython-0.45.0}/src/videopython/ai/video_analysis/stages.py +0 -0
- {videopython-0.44.1 → videopython-0.45.0}/src/videopython/audio/__init__.py +0 -0
- {videopython-0.44.1 → videopython-0.45.0}/src/videopython/audio/analysis.py +0 -0
- {videopython-0.44.1 → videopython-0.45.0}/src/videopython/audio/audio.py +0 -0
- {videopython-0.44.1 → videopython-0.45.0}/src/videopython/base/__init__.py +0 -0
- {videopython-0.44.1 → videopython-0.45.0}/src/videopython/base/_dimensions.py +0 -0
- {videopython-0.44.1 → videopython-0.45.0}/src/videopython/base/_ffmpeg.py +0 -0
- {videopython-0.44.1 → videopython-0.45.0}/src/videopython/base/_video_io.py +0 -0
- {videopython-0.44.1 → videopython-0.45.0}/src/videopython/base/description.py +0 -0
- {videopython-0.44.1 → videopython-0.45.0}/src/videopython/base/draw_detections.py +0 -0
- {videopython-0.44.1 → videopython-0.45.0}/src/videopython/base/fonts/Anton-OFL.txt +0 -0
- {videopython-0.44.1 → videopython-0.45.0}/src/videopython/base/fonts/Anton-Regular.ttf +0 -0
- {videopython-0.44.1 → videopython-0.45.0}/src/videopython/base/fonts/BebasNeue-OFL.txt +0 -0
- {videopython-0.44.1 → videopython-0.45.0}/src/videopython/base/fonts/BebasNeue-Regular.ttf +0 -0
- {videopython-0.44.1 → videopython-0.45.0}/src/videopython/base/fonts/DejaVuSans.ttf +0 -0
- {videopython-0.44.1 → videopython-0.45.0}/src/videopython/base/fonts/LICENSE_DEJAVU +0 -0
- {videopython-0.44.1 → videopython-0.45.0}/src/videopython/base/fonts/Lato-Bold.ttf +0 -0
- {videopython-0.44.1 → videopython-0.45.0}/src/videopython/base/fonts/Lato-OFL.txt +0 -0
- {videopython-0.44.1 → videopython-0.45.0}/src/videopython/base/fonts/Poppins-Bold.ttf +0 -0
- {videopython-0.44.1 → videopython-0.45.0}/src/videopython/base/fonts/Poppins-OFL.txt +0 -0
- {videopython-0.44.1 → videopython-0.45.0}/src/videopython/base/fonts/__init__.py +0 -0
- {videopython-0.44.1 → videopython-0.45.0}/src/videopython/base/transcription.py +0 -0
- {videopython-0.44.1 → videopython-0.45.0}/src/videopython/base/video.py +0 -0
- {videopython-0.44.1 → videopython-0.45.0}/src/videopython/editing/__init__.py +0 -0
- {videopython-0.44.1 → videopython-0.45.0}/src/videopython/editing/_ass.py +0 -0
- {videopython-0.44.1 → videopython-0.45.0}/src/videopython/editing/_easing.py +0 -0
- {videopython-0.44.1 → videopython-0.45.0}/src/videopython/editing/audio_ops.py +0 -0
- {videopython-0.44.1 → videopython-0.45.0}/src/videopython/editing/effects.py +0 -0
- {videopython-0.44.1 → videopython-0.45.0}/src/videopython/editing/operation.py +0 -0
- {videopython-0.44.1 → videopython-0.45.0}/src/videopython/editing/transcription_overlay.py +0 -0
- {videopython-0.44.1 → videopython-0.45.0}/src/videopython/editing/transforms.py +0 -0
- {videopython-0.44.1 → videopython-0.45.0}/src/videopython/py.typed +0 -0
|
@@ -96,7 +96,7 @@ class PlanErrorCode(str, Enum):
|
|
|
96
96
|
TRANSITION_TOO_LONG = "transition_too_long"
|
|
97
97
|
MUSIC_BED_DUCK_MULTISEGMENT = "music_bed_duck_multisegment"
|
|
98
98
|
# Streaming: unstreamable op at its plan position (always reported).
|
|
99
|
-
|
|
99
|
+
STREAMING_UNSUPPORTED = "streaming_unsupported"
|
|
100
100
|
|
|
101
101
|
|
|
102
102
|
@dataclass
|
|
@@ -36,8 +36,8 @@ class StreamingClass(str, Enum):
|
|
|
36
36
|
|
|
37
37
|
``FILTER`` and ``FRAME_EFFECT`` stream in O(1) memory w.r.t. video
|
|
38
38
|
length. ``UNSTREAMABLE`` means the op (or its plan position) has no
|
|
39
|
-
streaming strategy;
|
|
40
|
-
|
|
39
|
+
streaming strategy; such plans are rejected with structured
|
|
40
|
+
``STREAMING_UNSUPPORTED`` errors.
|
|
41
41
|
"""
|
|
42
42
|
|
|
43
43
|
FILTER = "filter"
|
|
@@ -85,19 +85,19 @@ class StreamabilityReport:
|
|
|
85
85
|
return all(e.streams for e in self.entries)
|
|
86
86
|
|
|
87
87
|
@property
|
|
88
|
-
def
|
|
88
|
+
def unstreamable(self) -> tuple[OpStreamability, ...]:
|
|
89
89
|
"""The unstreamable ops, in plan order."""
|
|
90
90
|
return tuple(e for e in self.entries if not e.streams)
|
|
91
91
|
|
|
92
92
|
def errors(self) -> list[PlanError]:
|
|
93
|
-
"""The
|
|
93
|
+
"""The unstreamable ops as structured ``STREAMING_UNSUPPORTED`` plan errors.
|
|
94
94
|
|
|
95
95
|
The same shape :meth:`VideoEdit.check` returns, so an LLM refine loop
|
|
96
96
|
can treat "would not stream" exactly like any other plan violation.
|
|
97
97
|
"""
|
|
98
98
|
return [
|
|
99
|
-
PlanError(code=PlanErrorCode.
|
|
100
|
-
for e in self.
|
|
99
|
+
PlanError(code=PlanErrorCode.STREAMING_UNSUPPORTED, location=e.location, op=e.op, detail=e.reason)
|
|
100
|
+
for e in self.unstreamable
|
|
101
101
|
]
|
|
102
102
|
|
|
103
103
|
|
|
@@ -115,7 +115,7 @@ def analyze_streamability(
|
|
|
115
115
|
``streamable`` ClassVar as the authoritative declaration (a flag-False
|
|
116
116
|
transform never streams, even with a working ``to_ffmpeg_filter``); the
|
|
117
117
|
one divergence the flag cannot express -- flag True but the filter
|
|
118
|
-
compiles to ``None`` -- is caught at runtime by the ``
|
|
118
|
+
compiles to ``None`` -- is caught at runtime by the ``STREAMING_UNSUPPORTED``
|
|
119
119
|
raise in ``_compile_streaming_plans``, and a registry test pins flag-True
|
|
120
120
|
transforms to an actual ``to_ffmpeg_filter`` override. Purely structural:
|
|
121
121
|
no disk access and no runtime context.
|
|
@@ -1036,7 +1036,7 @@ class VideoEdit(BaseModel):
|
|
|
1036
1036
|
:meth:`validate`: a clampable ``window.stop`` overrun is not reported.
|
|
1037
1037
|
|
|
1038
1038
|
Streaming is the only engine, so ops that cannot stream at their
|
|
1039
|
-
plan position are real plan errors: one ``
|
|
1039
|
+
plan position are real plan errors: one ``STREAMING_UNSUPPORTED`` per
|
|
1040
1040
|
offending op is appended after the validity errors, in plan order,
|
|
1041
1041
|
with the actionable cause in :attr:`PlanError.detail`. See
|
|
1042
1042
|
:meth:`streamability` for the full per-op report including the ops
|
|
@@ -1056,7 +1056,7 @@ class VideoEdit(BaseModel):
|
|
|
1056
1056
|
admitted. ``report.streamable`` answers "will :meth:`run_to_file`
|
|
1057
1057
|
stream this plan in O(1) memory, or is an op unstreamable at its
|
|
1058
1058
|
plan position?"; each entry carries the op's memory class and, for
|
|
1059
|
-
|
|
1059
|
+
unstreamable ops, the reason.
|
|
1060
1060
|
"""
|
|
1061
1061
|
return analyze_streamability(
|
|
1062
1062
|
[list(seg.operations) for seg in self.segments],
|
|
@@ -1603,7 +1603,7 @@ class VideoEdit(BaseModel):
|
|
|
1603
1603
|
Memory usage is O(1) w.r.t. video length (video; segment audio is
|
|
1604
1604
|
in-memory). Streaming is the only engine: a plan with an unstreamable
|
|
1605
1605
|
shape raises :class:`PlanValidationError` carrying one
|
|
1606
|
-
``
|
|
1606
|
+
``STREAMING_UNSUPPORTED`` :class:`PlanError` per offending op -- before
|
|
1607
1607
|
any decode. Gate plans early with :meth:`check` or
|
|
1608
1608
|
:meth:`streamability`, which report the same errors without running
|
|
1609
1609
|
anything.
|
|
@@ -1834,16 +1834,16 @@ class VideoEdit(BaseModel):
|
|
|
1834
1834
|
:class:`PlanValidationError` with the streamability report's
|
|
1835
1835
|
structured errors; a builder/report drift (e.g. a third-party
|
|
1836
1836
|
transform whose ``streamable`` flag does not match its
|
|
1837
|
-
``to_ffmpeg_filter``) raises with a generic ``
|
|
1837
|
+
``to_ffmpeg_filter``) raises with a generic ``STREAMING_UNSUPPORTED``.
|
|
1838
1838
|
On raise, any compile-time temp files already created are deleted;
|
|
1839
1839
|
on success the caller owns ``plan.owned_temp_files``.
|
|
1840
1840
|
"""
|
|
1841
1841
|
self._assert_post_ops_supported(context)
|
|
1842
1842
|
report = self.streamability()
|
|
1843
1843
|
if not report.streamable:
|
|
1844
|
-
causes = "; ".join(f"{e.location} '{e.op}': {e.reason}" for e in report.
|
|
1844
|
+
causes = "; ".join(f"{e.location} '{e.op}': {e.reason}" for e in report.unstreamable)
|
|
1845
1845
|
message = (
|
|
1846
|
-
f"Plan cannot stream: {len(report.
|
|
1846
|
+
f"Plan cannot stream: {len(report.unstreamable)} op(s) have no streaming "
|
|
1847
1847
|
f"strategy at their plan position -- {causes}"
|
|
1848
1848
|
)
|
|
1849
1849
|
raise PlanValidationError(message, report.errors())
|
|
@@ -1851,7 +1851,7 @@ class VideoEdit(BaseModel):
|
|
|
1851
1851
|
def drift(detail: str) -> PlanValidationError:
|
|
1852
1852
|
return PlanValidationError(
|
|
1853
1853
|
f"plan stopped streaming despite a clean streamability report ({detail})",
|
|
1854
|
-
[PlanError(code=PlanErrorCode.
|
|
1854
|
+
[PlanError(code=PlanErrorCode.STREAMING_UNSUPPORTED, detail=detail)],
|
|
1855
1855
|
)
|
|
1856
1856
|
|
|
1857
1857
|
target_fps, target_w, target_h = self._matching_targets_from_disk()
|
|
@@ -2090,7 +2090,7 @@ class VideoEdit(BaseModel):
|
|
|
2090
2090
|
# flag-False transform is classified UNSTREAMABLE even if it has
|
|
2091
2091
|
# a working to_ffmpeg_filter. The remaining drift class (flag
|
|
2092
2092
|
# True, filter compiles to None) is caught by the
|
|
2093
|
-
#
|
|
2093
|
+
# STREAMING_UNSUPPORTED raise in _compile_streaming_plans.
|
|
2094
2094
|
if not op.streamable:
|
|
2095
2095
|
abandon()
|
|
2096
2096
|
return None
|
|
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
|
|
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
|