Prepare recordings

This commit is contained in:
Nirvana
2026-03-20 14:35:38 +01:00
parent 75f2a97e2e
commit 189a40e866
+131
View File
@@ -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)
# =========================================================================