eaf_base_api 4.1.0__tar.gz → 4.1.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.
- {eaf_base_api-4.1.0 → eaf_base_api-4.1.1}/PKG-INFO +1 -1
- {eaf_base_api-4.1.0 → eaf_base_api-4.1.1}/base_api/base.py +63 -1
- {eaf_base_api-4.1.0 → eaf_base_api-4.1.1}/pyproject.toml +1 -1
- {eaf_base_api-4.1.0 → eaf_base_api-4.1.1}/LICENSE +0 -0
- {eaf_base_api-4.1.0 → eaf_base_api-4.1.1}/README.md +0 -0
- {eaf_base_api-4.1.0 → eaf_base_api-4.1.1}/base_api/__init__.py +0 -0
- {eaf_base_api-4.1.0 → eaf_base_api-4.1.1}/base_api/modules/__init__.py +0 -0
- {eaf_base_api-4.1.0 → eaf_base_api-4.1.1}/base_api/modules/config.py +0 -0
- {eaf_base_api-4.1.0 → eaf_base_api-4.1.1}/base_api/modules/errors.py +0 -0
- {eaf_base_api-4.1.0 → eaf_base_api-4.1.1}/base_api/modules/logger.py +0 -0
- {eaf_base_api-4.1.0 → eaf_base_api-4.1.1}/base_api/modules/progress_bars.py +0 -0
- {eaf_base_api-4.1.0 → eaf_base_api-4.1.1}/base_api/modules/static_functions.py +0 -0
- {eaf_base_api-4.1.0 → eaf_base_api-4.1.1}/base_api/modules/type_hints.py +0 -0
- {eaf_base_api-4.1.0 → eaf_base_api-4.1.1}/base_api/py.typed +0 -0
|
@@ -102,6 +102,47 @@ def _contains_http_status(error: BaseException, status_code: int) -> bool:
|
|
|
102
102
|
return False
|
|
103
103
|
|
|
104
104
|
|
|
105
|
+
def _normalize_packet_timestamps(
|
|
106
|
+
packet: Any,
|
|
107
|
+
offsets: dict[int, int],
|
|
108
|
+
last_dts: dict[int, int],
|
|
109
|
+
last_durations: dict[int, int],
|
|
110
|
+
) -> int:
|
|
111
|
+
"""Keep remuxed packet timestamps continuous across HLS discontinuities."""
|
|
112
|
+
if packet.dts is None:
|
|
113
|
+
return 0
|
|
114
|
+
|
|
115
|
+
stream_index = packet.stream.index
|
|
116
|
+
raw_dts = packet.dts
|
|
117
|
+
offset = offsets.get(stream_index, 0)
|
|
118
|
+
normalized_dts = raw_dts + offset
|
|
119
|
+
previous_dts = last_dts.get(stream_index)
|
|
120
|
+
correction = 0
|
|
121
|
+
|
|
122
|
+
if previous_dts is not None:
|
|
123
|
+
step = max(1, last_durations.get(stream_index, packet.duration or 1))
|
|
124
|
+
expected_dts = previous_dts + step
|
|
125
|
+
try:
|
|
126
|
+
ten_seconds = max(1, int(10 / float(packet.time_base)))
|
|
127
|
+
except (TypeError, ValueError, ZeroDivisionError):
|
|
128
|
+
ten_seconds = step * 240
|
|
129
|
+
|
|
130
|
+
discontinuity_threshold = max(step * 10, ten_seconds)
|
|
131
|
+
delta = normalized_dts - expected_dts
|
|
132
|
+
if normalized_dts <= previous_dts or abs(delta) > discontinuity_threshold:
|
|
133
|
+
correction = -delta
|
|
134
|
+
offset += correction
|
|
135
|
+
offsets[stream_index] = offset
|
|
136
|
+
normalized_dts = raw_dts + offset
|
|
137
|
+
|
|
138
|
+
packet.dts = normalized_dts
|
|
139
|
+
if packet.pts is not None:
|
|
140
|
+
packet.pts += offset
|
|
141
|
+
last_dts[stream_index] = normalized_dts
|
|
142
|
+
last_durations[stream_index] = max(1, packet.duration or 1)
|
|
143
|
+
return correction
|
|
144
|
+
|
|
145
|
+
|
|
105
146
|
@dataclass(frozen=True, slots=True)
|
|
106
147
|
class RequestCacheKey:
|
|
107
148
|
"""Identity of a cacheable HTTP request without retaining credentials."""
|
|
@@ -2798,7 +2839,11 @@ class BaseCore:
|
|
|
2798
2839
|
if remux:
|
|
2799
2840
|
self.logger.info(f"Remuxing TS to MP4: input={tmp_path} output={path}")
|
|
2800
2841
|
# Offload heavy CPU/IO bound task
|
|
2801
|
-
|
|
2842
|
+
try:
|
|
2843
|
+
await asyncio.to_thread(self._convert_ts_to_mp4, tmp_path, path, callback_remux, ios_support)
|
|
2844
|
+
except Exception:
|
|
2845
|
+
self._safe_remove(path)
|
|
2846
|
+
raise
|
|
2802
2847
|
# This is important, because not all players can play MPEG-TS AND I want to write
|
|
2803
2848
|
# metadata to the files, and this doesn't work without a container.
|
|
2804
2849
|
self._safe_remove(tmp_path)
|
|
@@ -2928,6 +2973,9 @@ class BaseCore:
|
|
|
2928
2973
|
progress_step = max(1, total // 10) if total else 0
|
|
2929
2974
|
next_progress_log = progress_step if progress_step else 0
|
|
2930
2975
|
current_progress = 0
|
|
2976
|
+
timestamp_offsets: dict[int, int] = {}
|
|
2977
|
+
last_dts: dict[int, int] = {}
|
|
2978
|
+
last_durations: dict[int, int] = {}
|
|
2931
2979
|
|
|
2932
2980
|
for idx, packet in enumerate(packets):
|
|
2933
2981
|
pkt_size = getattr(packet, "size", 0) or 0
|
|
@@ -2938,6 +2986,20 @@ class BaseCore:
|
|
|
2938
2986
|
callback(current_progress, total)
|
|
2939
2987
|
continue
|
|
2940
2988
|
|
|
2989
|
+
timestamp_correction = _normalize_packet_timestamps(
|
|
2990
|
+
packet,
|
|
2991
|
+
timestamp_offsets,
|
|
2992
|
+
last_dts,
|
|
2993
|
+
last_durations,
|
|
2994
|
+
)
|
|
2995
|
+
if timestamp_correction:
|
|
2996
|
+
self.logger.info(
|
|
2997
|
+
"Normalized HLS timestamp discontinuity: stream=%s correction=%s time_base=%s",
|
|
2998
|
+
packet.stream.index,
|
|
2999
|
+
timestamp_correction,
|
|
3000
|
+
packet.time_base,
|
|
3001
|
+
)
|
|
3002
|
+
|
|
2941
3003
|
if packet.stream == in_video:
|
|
2942
3004
|
packet.stream = out_video
|
|
2943
3005
|
output.mux(packet)
|
|
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
|