mirror of
https://github.com/nirvana-7777/script.service.ultimate.git
synced 2026-09-19 15:42:13 +02:00
155 lines
5.7 KiB
Python
155 lines
5.7 KiB
Python
# streaming_providers/base/utils/manifest_parser.py
|
|
"""
|
|
DASH manifest parser for extracting init segment URLs.
|
|
For PSSH/DRM extraction, use drm_extractor module.
|
|
"""
|
|
|
|
from typing import Optional, List
|
|
|
|
from .logger import logger
|
|
from .url_resolver import URLResolver
|
|
from .manifest_utils import ManifestUtils
|
|
|
|
|
|
class ManifestParser:
|
|
"""Parser for DASH manifests focused on segment URL extraction."""
|
|
|
|
# ========================================================================
|
|
# Backwards Compatibility: DRM Methods (Delegate to DRMExtractor)
|
|
# ========================================================================
|
|
# These methods are kept for backwards compatibility with code that calls
|
|
# ManifestParser._extract_from_manifest_content() etc.
|
|
# They simply delegate to DRMExtractor.
|
|
|
|
@staticmethod
|
|
def _extract_from_manifest_content(manifest_content: str):
|
|
"""
|
|
DEPRECATED: Use DRMExtractor._extract_from_manifest_content() instead.
|
|
Kept for backwards compatibility.
|
|
"""
|
|
from .drm_extractor import DRMExtractor
|
|
return DRMExtractor._extract_from_manifest_content(manifest_content)
|
|
|
|
@staticmethod
|
|
def _extract_from_single_segment(segment_url: str, expected_system_ids: List[str] = None):
|
|
"""
|
|
DEPRECATED: Use DRMExtractor._extract_from_single_segment() instead.
|
|
Kept for backwards compatibility.
|
|
"""
|
|
from .drm_extractor import DRMExtractor
|
|
return DRMExtractor._extract_from_single_segment(segment_url, expected_system_ids)
|
|
|
|
@staticmethod
|
|
def _merge_pssh_data(manifest_pssh: List, segment_pssh: List):
|
|
"""
|
|
DEPRECATED: Use DRMExtractor._merge_pssh_data() instead.
|
|
Kept for backwards compatibility.
|
|
"""
|
|
from .drm_extractor import DRMExtractor
|
|
return DRMExtractor._merge_pssh_data(manifest_pssh, segment_pssh)
|
|
|
|
# ========================================================================
|
|
# Segment URL Extraction (Primary Purpose)
|
|
# ========================================================================
|
|
|
|
@staticmethod
|
|
def extract_single_init_segment_url(
|
|
manifest_content: str,
|
|
manifest_url: str
|
|
) -> Optional[str]:
|
|
"""
|
|
Extract ONE init segment URL from DASH manifest.
|
|
Prioritizes video representations as they typically have the same DRM as audio.
|
|
|
|
Args:
|
|
manifest_content: Full manifest XML content
|
|
manifest_url: URL where the manifest was fetched from
|
|
|
|
Returns:
|
|
Full URL to an initialization segment, or None if not found
|
|
"""
|
|
# Build effective base URL from manifest URL and BaseURL elements
|
|
base_urls = ManifestUtils.extract_base_urls(manifest_content)
|
|
effective_base = URLResolver.build_effective_base_url(manifest_url, base_urls)
|
|
|
|
logger.debug(f"Effective base URL: {effective_base}")
|
|
|
|
# Parse all adaptation sets
|
|
adaptation_sets = ManifestUtils.parse_adaptation_sets(manifest_content)
|
|
video_sets, audio_sets = ManifestUtils.separate_video_audio_sets(adaptation_sets)
|
|
|
|
# Try video first, then audio
|
|
target_sets = video_sets + audio_sets
|
|
|
|
for ad_set_info in target_sets:
|
|
# Extract SegmentTemplate initialization attribute
|
|
init_template = ManifestUtils.extract_segment_template_initialization(
|
|
ad_set_info.content
|
|
)
|
|
|
|
if not init_template:
|
|
continue
|
|
|
|
logger.debug(f"Found init template: {init_template}")
|
|
|
|
# Get first Representation ID from this AdaptationSet
|
|
rep_id = ManifestUtils.extract_first_representation_id(ad_set_info.content)
|
|
|
|
if not rep_id:
|
|
logger.debug("No Representation ID found in AdaptationSet")
|
|
continue
|
|
|
|
logger.debug(f"Using Representation ID: {rep_id}")
|
|
|
|
# Substitute template variables with defaults
|
|
init_url = URLResolver.substitute_template_variables(
|
|
init_template,
|
|
representation_id=rep_id,
|
|
bandwidth="0",
|
|
time="0",
|
|
number="1"
|
|
)
|
|
|
|
# Construct full URL
|
|
full_url = URLResolver.construct_full_url(
|
|
effective_base,
|
|
init_url,
|
|
url_encode_filename=True
|
|
)
|
|
|
|
logger.info(f"Constructed init segment URL: {full_url}")
|
|
return full_url
|
|
|
|
logger.warning("Could not find init segment URL in manifest")
|
|
return None
|
|
|
|
@staticmethod
|
|
def extract_segment_urls(manifest_content: str, manifest_url: str) -> List[str]:
|
|
"""
|
|
DEPRECATED: Use extract_single_init_segment_url instead.
|
|
This extracts ALL segments which is inefficient.
|
|
|
|
This method is kept for backwards compatibility only.
|
|
"""
|
|
logger.warning(
|
|
"extract_segment_urls is deprecated, use extract_single_init_segment_url"
|
|
)
|
|
init_url = ManifestParser.extract_single_init_segment_url(
|
|
manifest_content, manifest_url
|
|
)
|
|
return [init_url] if init_url else []
|
|
|
|
@staticmethod
|
|
def extract_init_segment_urls(manifest_content: str, manifest_url: str) -> List[str]:
|
|
"""
|
|
DEPRECATED: Use extract_single_init_segment_url instead.
|
|
|
|
This method is kept for backwards compatibility only.
|
|
"""
|
|
logger.warning(
|
|
"extract_init_segment_urls is deprecated, use extract_single_init_segment_url"
|
|
)
|
|
init_url = ManifestParser.extract_single_init_segment_url(
|
|
manifest_content, manifest_url
|
|
)
|
|
return [init_url] if init_url else [] |