mirror of
https://github.com/nirvana-7777/script.service.ultimate.git
synced 2026-10-24 16:52:38 +02:00
Prepare recordings
This commit is contained in:
@@ -36,6 +36,7 @@ from streaming_providers.base.utils import logger
|
||||
CONTENT_TYPE_CHANNEL = "channel"
|
||||
CONTENT_TYPE_EVENT = "event"
|
||||
CONTENT_TYPE_VOD = "vod"
|
||||
CONTENT_TYPE_RECORDING = "recording"
|
||||
|
||||
|
||||
def setup_stream_routes(app, manager, service):
|
||||
@@ -63,6 +64,10 @@ def setup_stream_routes(app, manager, service):
|
||||
return manager.get_vod_drm_configs(
|
||||
provider_name=provider, vod_id=content_id, **kwargs
|
||||
)
|
||||
elif content_type == CONTENT_TYPE_RECORDING:
|
||||
return manager.get_recording_drm_configs(
|
||||
provider_name=provider, recording_id=content_id, **kwargs
|
||||
)
|
||||
else:
|
||||
raise ValueError(f"Unknown content_type '{content_type}'")
|
||||
|
||||
@@ -83,6 +88,10 @@ def setup_stream_routes(app, manager, service):
|
||||
return manager.get_vod_manifest(
|
||||
provider_name=provider, vod_id=content_id, **kwargs
|
||||
)
|
||||
elif content_type == CONTENT_TYPE_RECORDING:
|
||||
return manager.get_recording_manifest(
|
||||
provider_name=provider, recording_id=content_id, **kwargs
|
||||
)
|
||||
else:
|
||||
raise ValueError(f"Unknown content_type '{content_type}'")
|
||||
|
||||
@@ -695,6 +704,128 @@ def setup_stream_routes(app, manager, service):
|
||||
response.status = 500
|
||||
return {"error": f"Internal server error: {str(e)}"}
|
||||
|
||||
# =========================================================================
|
||||
# RECORDING ROUTES — identical transport pattern to VOD routes
|
||||
#
|
||||
# Recordings are always on-demand (pre-captured), so:
|
||||
# - No catchup path (unlike channels)
|
||||
# - No ffmpeg variant (not a live/adaptive stream that needs quality pinning)
|
||||
# - recording_id is a flat identifier, no path hierarchy needed
|
||||
#
|
||||
# /manifest → returns local stream URL + attaches DRM header
|
||||
# /stream → proxy-rewrites or redirects to upstream manifest
|
||||
# /drm → returns raw DRM configs
|
||||
# =========================================================================
|
||||
|
||||
@app.route("/api/providers/<provider>/recordings/<recording_id>/manifest")
|
||||
def get_recording_manifest(provider, recording_id):
|
||||
"""
|
||||
Returns JSON with a manifest_url pointing to the recording stream endpoint.
|
||||
Attaches x-kodi-drm-configs header.
|
||||
"""
|
||||
try:
|
||||
country = request.query.get("country")
|
||||
base_url = f"{request.urlparts.scheme}://{request.urlparts.netloc}"
|
||||
stream_url = (
|
||||
f"{base_url}/api/providers/{provider}"
|
||||
f"/recordings/{recording_id}/stream/index.mpd"
|
||||
)
|
||||
if country:
|
||||
stream_url += f"?country={country}"
|
||||
|
||||
_build_drm_header(
|
||||
CONTENT_TYPE_RECORDING, provider, recording_id, country=country
|
||||
)
|
||||
|
||||
return {
|
||||
"provider": provider,
|
||||
"recording_id": recording_id,
|
||||
"manifest_url": stream_url,
|
||||
}
|
||||
|
||||
except ValueError as e:
|
||||
logger.error(
|
||||
f"manifest endpoint error for recording {provider}/{recording_id}: {e}"
|
||||
)
|
||||
response.status = 404
|
||||
return {"error": str(e)}
|
||||
except Exception as e:
|
||||
logger.error(
|
||||
f"manifest endpoint error for recording {provider}/{recording_id}: {e}"
|
||||
)
|
||||
response.status = 500
|
||||
return {"error": f"Internal server error: {str(e)}"}
|
||||
|
||||
@app.route("/api/providers/<provider>/recordings/<recording_id>/stream/index.mpd")
|
||||
def get_recording_stream(provider, recording_id):
|
||||
"""
|
||||
Returns HTTP 302 redirect to the recording manifest, or a rewritten
|
||||
manifest body when media proxy is active.
|
||||
"""
|
||||
try:
|
||||
country = request.query.get("country")
|
||||
return _resolve_stream(
|
||||
CONTENT_TYPE_RECORDING, provider, recording_id, country=country
|
||||
)
|
||||
except HTTPResponse:
|
||||
raise
|
||||
except ValueError as e:
|
||||
logger.error(
|
||||
f"stream error for recording {provider}/{recording_id}: {e}"
|
||||
)
|
||||
response.status = 404
|
||||
return {"error": str(e)}
|
||||
except Exception as e:
|
||||
logger.error(
|
||||
f"stream error for recording {provider}/{recording_id}: {e}"
|
||||
)
|
||||
response.status = 500
|
||||
return {"error": f"Internal server error: {str(e)}"}
|
||||
|
||||
@app.route(
|
||||
"/api/providers/<provider>/recordings/<recording_id>/stream/decrypted/index.mpd"
|
||||
)
|
||||
def get_recording_stream_decrypted(provider, recording_id):
|
||||
"""Decrypted recording stream — all quality representations."""
|
||||
return _resolve_decrypted_stream(
|
||||
CONTENT_TYPE_RECORDING, provider, recording_id, highest_quality_only=False
|
||||
)
|
||||
|
||||
@app.route("/api/providers/<provider>/recordings/<recording_id>/drm")
|
||||
def get_recording_drm(provider, recording_id):
|
||||
"""Return DRM configs for a specific recording."""
|
||||
try:
|
||||
country = request.query.get("country")
|
||||
drm_configs = _get_drm_configs(
|
||||
CONTENT_TYPE_RECORDING, provider, recording_id, country=country
|
||||
)
|
||||
|
||||
merged = {}
|
||||
for config in drm_configs:
|
||||
merged.update(
|
||||
config.to_dict() if hasattr(config, "to_dict") else config
|
||||
)
|
||||
|
||||
return {
|
||||
"provider": provider,
|
||||
"recording_id": recording_id,
|
||||
"content_type": CONTENT_TYPE_RECORDING,
|
||||
"drm_configs": merged,
|
||||
}
|
||||
|
||||
except ValueError as e:
|
||||
logger.error(
|
||||
f"DRM endpoint error for recording {provider}/{recording_id}: {e}"
|
||||
)
|
||||
response.status = 404
|
||||
return {"error": str(e)}
|
||||
except Exception as e:
|
||||
logger.error(
|
||||
f"DRM endpoint error for recording {provider}/{recording_id}: {e}"
|
||||
)
|
||||
response.status = 500
|
||||
return {"error": f"Internal server error: {str(e)}"}
|
||||
|
||||
# =========================================================================
|
||||
# EPG ROUTES (unchanged from original)
|
||||
# =========================================================================
|
||||
|
||||
Reference in New Issue
Block a user