@svta/cml-cmaf-ham 0.19.0 → 0.20.0
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.
- package/README.md +6 -0
- package/dist/index.d.ts +1273 -51
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1822 -19
- package/dist/index.js.map +1 -1
- package/package.json +6 -26
- package/dist/mapper/Mapper.d.ts +0 -8
- package/dist/mapper/Mapper.d.ts.map +0 -1
- package/dist/mapper/Mapper.js +0 -2
- package/dist/mapper/Mapper.js.map +0 -1
- package/dist/mapper/MapperContext.d.ts +0 -14
- package/dist/mapper/MapperContext.d.ts.map +0 -1
- package/dist/mapper/MapperContext.js +0 -22
- package/dist/mapper/MapperContext.js.map +0 -1
- package/dist/mapper/dash/DashMapper.d.ts +0 -10
- package/dist/mapper/dash/DashMapper.d.ts.map +0 -1
- package/dist/mapper/dash/DashMapper.js +0 -23
- package/dist/mapper/dash/DashMapper.js.map +0 -1
- package/dist/mapper/dash/mapDashToHam/mapDashToHam.d.ts +0 -12
- package/dist/mapper/dash/mapDashToHam/mapDashToHam.d.ts.map +0 -1
- package/dist/mapper/dash/mapDashToHam/mapDashToHam.js +0 -42
- package/dist/mapper/dash/mapDashToHam/mapDashToHam.js.map +0 -1
- package/dist/mapper/dash/mapDashToHam/mapSegmentBase.d.ts +0 -13
- package/dist/mapper/dash/mapDashToHam/mapSegmentBase.d.ts.map +0 -1
- package/dist/mapper/dash/mapDashToHam/mapSegmentBase.js +0 -20
- package/dist/mapper/dash/mapDashToHam/mapSegmentBase.js.map +0 -1
- package/dist/mapper/dash/mapDashToHam/mapSegmentList.d.ts +0 -12
- package/dist/mapper/dash/mapDashToHam/mapSegmentList.d.ts.map +0 -1
- package/dist/mapper/dash/mapDashToHam/mapSegmentList.js +0 -25
- package/dist/mapper/dash/mapDashToHam/mapSegmentList.js.map +0 -1
- package/dist/mapper/dash/mapDashToHam/mapSegmentTemplate.d.ts +0 -15
- package/dist/mapper/dash/mapDashToHam/mapSegmentTemplate.d.ts.map +0 -1
- package/dist/mapper/dash/mapDashToHam/mapSegmentTemplate.js +0 -27
- package/dist/mapper/dash/mapDashToHam/mapSegmentTemplate.js.map +0 -1
- package/dist/mapper/dash/mapDashToHam/mapSegments.d.ts +0 -20
- package/dist/mapper/dash/mapDashToHam/mapSegments.d.ts.map +0 -1
- package/dist/mapper/dash/mapDashToHam/mapSegments.js +0 -37
- package/dist/mapper/dash/mapDashToHam/mapSegments.js.map +0 -1
- package/dist/mapper/dash/mapDashToHam/mapTracks.d.ts +0 -19
- package/dist/mapper/dash/mapDashToHam/mapTracks.d.ts.map +0 -1
- package/dist/mapper/dash/mapDashToHam/mapTracks.js +0 -72
- package/dist/mapper/dash/mapDashToHam/mapTracks.js.map +0 -1
- package/dist/mapper/dash/mapDashToHam/utils/calculateDuration.d.ts +0 -13
- package/dist/mapper/dash/mapDashToHam/utils/calculateDuration.d.ts.map +0 -1
- package/dist/mapper/dash/mapDashToHam/utils/calculateDuration.js +0 -18
- package/dist/mapper/dash/mapDashToHam/utils/calculateDuration.js.map +0 -1
- package/dist/mapper/dash/mapDashToHam/utils/getChannels.d.ts +0 -13
- package/dist/mapper/dash/mapDashToHam/utils/getChannels.d.ts.map +0 -1
- package/dist/mapper/dash/mapDashToHam/utils/getChannels.js +0 -18
- package/dist/mapper/dash/mapDashToHam/utils/getChannels.js.map +0 -1
- package/dist/mapper/dash/mapDashToHam/utils/getCodec.d.ts +0 -13
- package/dist/mapper/dash/mapDashToHam/utils/getCodec.d.ts.map +0 -1
- package/dist/mapper/dash/mapDashToHam/utils/getCodec.js +0 -18
- package/dist/mapper/dash/mapDashToHam/utils/getCodec.js.map +0 -1
- package/dist/mapper/dash/mapDashToHam/utils/getContentType.d.ts +0 -14
- package/dist/mapper/dash/mapDashToHam/utils/getContentType.d.ts.map +0 -1
- package/dist/mapper/dash/mapDashToHam/utils/getContentType.js +0 -37
- package/dist/mapper/dash/mapDashToHam/utils/getContentType.js.map +0 -1
- package/dist/mapper/dash/mapDashToHam/utils/getFrameRate.d.ts +0 -16
- package/dist/mapper/dash/mapDashToHam/utils/getFrameRate.d.ts.map +0 -1
- package/dist/mapper/dash/mapDashToHam/utils/getFrameRate.js +0 -31
- package/dist/mapper/dash/mapDashToHam/utils/getFrameRate.js.map +0 -1
- package/dist/mapper/dash/mapDashToHam/utils/getGroup.d.ts +0 -3
- package/dist/mapper/dash/mapDashToHam/utils/getGroup.d.ts.map +0 -1
- package/dist/mapper/dash/mapDashToHam/utils/getGroup.js +0 -6
- package/dist/mapper/dash/mapDashToHam/utils/getGroup.js.map +0 -1
- package/dist/mapper/dash/mapDashToHam/utils/getInitializationUrl.d.ts +0 -14
- package/dist/mapper/dash/mapDashToHam/utils/getInitializationUrl.d.ts.map +0 -1
- package/dist/mapper/dash/mapDashToHam/utils/getInitializationUrl.js +0 -32
- package/dist/mapper/dash/mapDashToHam/utils/getInitializationUrl.js.map +0 -1
- package/dist/mapper/dash/mapDashToHam/utils/getLanguage.d.ts +0 -11
- package/dist/mapper/dash/mapDashToHam/utils/getLanguage.d.ts.map +0 -1
- package/dist/mapper/dash/mapDashToHam/utils/getLanguage.js +0 -17
- package/dist/mapper/dash/mapDashToHam/utils/getLanguage.js.map +0 -1
- package/dist/mapper/dash/mapDashToHam/utils/getNumberOfSegments.d.ts +0 -17
- package/dist/mapper/dash/mapDashToHam/utils/getNumberOfSegments.d.ts.map +0 -1
- package/dist/mapper/dash/mapDashToHam/utils/getNumberOfSegments.js +0 -21
- package/dist/mapper/dash/mapDashToHam/utils/getNumberOfSegments.js.map +0 -1
- package/dist/mapper/dash/mapDashToHam/utils/getPresentationId.d.ts +0 -13
- package/dist/mapper/dash/mapDashToHam/utils/getPresentationId.d.ts.map +0 -1
- package/dist/mapper/dash/mapDashToHam/utils/getPresentationId.js +0 -15
- package/dist/mapper/dash/mapDashToHam/utils/getPresentationId.js.map +0 -1
- package/dist/mapper/dash/mapDashToHam/utils/getSampleRate.d.ts +0 -13
- package/dist/mapper/dash/mapDashToHam/utils/getSampleRate.d.ts.map +0 -1
- package/dist/mapper/dash/mapDashToHam/utils/getSampleRate.js +0 -18
- package/dist/mapper/dash/mapDashToHam/utils/getSampleRate.js.map +0 -1
- package/dist/mapper/dash/mapDashToHam/utils/getSar.d.ts +0 -13
- package/dist/mapper/dash/mapDashToHam/utils/getSar.d.ts.map +0 -1
- package/dist/mapper/dash/mapDashToHam/utils/getSar.js +0 -18
- package/dist/mapper/dash/mapDashToHam/utils/getSar.js.map +0 -1
- package/dist/mapper/dash/mapDashToHam/utils/getTrackDuration.d.ts +0 -16
- package/dist/mapper/dash/mapDashToHam/utils/getTrackDuration.d.ts.map +0 -1
- package/dist/mapper/dash/mapDashToHam/utils/getTrackDuration.js +0 -19
- package/dist/mapper/dash/mapDashToHam/utils/getTrackDuration.js.map +0 -1
- package/dist/mapper/dash/mapDashToHam/utils/getUrlFromTemplate.d.ts +0 -18
- package/dist/mapper/dash/mapDashToHam/utils/getUrlFromTemplate.d.ts.map +0 -1
- package/dist/mapper/dash/mapDashToHam/utils/getUrlFromTemplate.js +0 -34
- package/dist/mapper/dash/mapDashToHam/utils/getUrlFromTemplate.js.map +0 -1
- package/dist/mapper/dash/mapHamToDash/mapHamToDash.d.ts +0 -3
- package/dist/mapper/dash/mapHamToDash/mapHamToDash.d.ts.map +0 -1
- package/dist/mapper/dash/mapHamToDash/mapHamToDash.js +0 -17
- package/dist/mapper/dash/mapHamToDash/mapHamToDash.js.map +0 -1
- package/dist/mapper/dash/mapHamToDash/presentationsToPeriods.d.ts +0 -4
- package/dist/mapper/dash/mapHamToDash/presentationsToPeriods.d.ts.map +0 -1
- package/dist/mapper/dash/mapHamToDash/presentationsToPeriods.js +0 -16
- package/dist/mapper/dash/mapHamToDash/presentationsToPeriods.js.map +0 -1
- package/dist/mapper/dash/mapHamToDash/selectionSetsToAdaptationSet.d.ts +0 -4
- package/dist/mapper/dash/mapHamToDash/selectionSetsToAdaptationSet.d.ts.map +0 -1
- package/dist/mapper/dash/mapHamToDash/selectionSetsToAdaptationSet.js +0 -22
- package/dist/mapper/dash/mapHamToDash/selectionSetsToAdaptationSet.js.map +0 -1
- package/dist/mapper/dash/mapHamToDash/trackToSegmentBase.d.ts +0 -4
- package/dist/mapper/dash/mapHamToDash/trackToSegmentBase.d.ts.map +0 -1
- package/dist/mapper/dash/mapHamToDash/trackToSegmentBase.js +0 -61
- package/dist/mapper/dash/mapHamToDash/trackToSegmentBase.js.map +0 -1
- package/dist/mapper/dash/mapHamToDash/trackToSegmentList.d.ts +0 -4
- package/dist/mapper/dash/mapHamToDash/trackToSegmentList.d.ts.map +0 -1
- package/dist/mapper/dash/mapHamToDash/trackToSegmentList.js +0 -27
- package/dist/mapper/dash/mapHamToDash/trackToSegmentList.js.map +0 -1
- package/dist/mapper/dash/mapHamToDash/tracksToRepresentation.d.ts +0 -4
- package/dist/mapper/dash/mapHamToDash/tracksToRepresentation.d.ts.map +0 -1
- package/dist/mapper/dash/mapHamToDash/tracksToRepresentation.js +0 -52
- package/dist/mapper/dash/mapHamToDash/tracksToRepresentation.js.map +0 -1
- package/dist/mapper/dash/mapHamToDash/utils/getFrameRate.d.ts +0 -13
- package/dist/mapper/dash/mapHamToDash/utils/getFrameRate.d.ts.map +0 -1
- package/dist/mapper/dash/mapHamToDash/utils/getFrameRate.js +0 -25
- package/dist/mapper/dash/mapHamToDash/utils/getFrameRate.js.map +0 -1
- package/dist/mapper/dash/mapHamToDash/utils/getTimescale.d.ts +0 -16
- package/dist/mapper/dash/mapHamToDash/utils/getTimescale.d.ts.map +0 -1
- package/dist/mapper/dash/mapHamToDash/utils/getTimescale.js +0 -30
- package/dist/mapper/dash/mapHamToDash/utils/getTimescale.js.map +0 -1
- package/dist/mapper/hls/HlsMapper.d.ts +0 -10
- package/dist/mapper/hls/HlsMapper.d.ts.map +0 -1
- package/dist/mapper/hls/HlsMapper.js +0 -17
- package/dist/mapper/hls/HlsMapper.js.map +0 -1
- package/dist/mapper/hls/mapHamToHls/generateManifestPlaylistPiece.d.ts +0 -8
- package/dist/mapper/hls/mapHamToHls/generateManifestPlaylistPiece.d.ts.map +0 -1
- package/dist/mapper/hls/mapHamToHls/generateManifestPlaylistPiece.js +0 -26
- package/dist/mapper/hls/mapHamToHls/generateManifestPlaylistPiece.js.map +0 -1
- package/dist/mapper/hls/mapHamToHls/mapHamToHls.d.ts +0 -4
- package/dist/mapper/hls/mapHamToHls/mapHamToHls.d.ts.map +0 -1
- package/dist/mapper/hls/mapHamToHls/mapHamToHls.js +0 -29
- package/dist/mapper/hls/mapHamToHls/mapHamToHls.js.map +0 -1
- package/dist/mapper/hls/mapHamToHls/utils/getByterange.d.ts +0 -14
- package/dist/mapper/hls/mapHamToHls/utils/getByterange.d.ts.map +0 -1
- package/dist/mapper/hls/mapHamToHls/utils/getByterange.js +0 -22
- package/dist/mapper/hls/mapHamToHls/utils/getByterange.js.map +0 -1
- package/dist/mapper/hls/mapHamToHls/utils/getPlaylistData.d.ts +0 -14
- package/dist/mapper/hls/mapHamToHls/utils/getPlaylistData.d.ts.map +0 -1
- package/dist/mapper/hls/mapHamToHls/utils/getPlaylistData.js +0 -16
- package/dist/mapper/hls/mapHamToHls/utils/getPlaylistData.js.map +0 -1
- package/dist/mapper/hls/mapHamToHls/utils/getSegments.d.ts +0 -13
- package/dist/mapper/hls/mapHamToHls/utils/getSegments.d.ts.map +0 -1
- package/dist/mapper/hls/mapHamToHls/utils/getSegments.js +0 -23
- package/dist/mapper/hls/mapHamToHls/utils/getSegments.js.map +0 -1
- package/dist/mapper/hls/mapHamToHls/utils/getUrlInitialization.d.ts +0 -14
- package/dist/mapper/hls/mapHamToHls/utils/getUrlInitialization.d.ts.map +0 -1
- package/dist/mapper/hls/mapHamToHls/utils/getUrlInitialization.js +0 -16
- package/dist/mapper/hls/mapHamToHls/utils/getUrlInitialization.js.map +0 -1
- package/dist/mapper/hls/mapHlsToHam/audioGroupsToSwitchingSets.d.ts +0 -16
- package/dist/mapper/hls/mapHlsToHam/audioGroupsToSwitchingSets.d.ts.map +0 -1
- package/dist/mapper/hls/mapHlsToHam/audioGroupsToSwitchingSets.js +0 -55
- package/dist/mapper/hls/mapHlsToHam/audioGroupsToSwitchingSets.js.map +0 -1
- package/dist/mapper/hls/mapHlsToHam/mapHlsToHam.d.ts +0 -4
- package/dist/mapper/hls/mapHlsToHam/mapHlsToHam.d.ts.map +0 -1
- package/dist/mapper/hls/mapHlsToHam/mapHlsToHam.js +0 -41
- package/dist/mapper/hls/mapHlsToHam/mapHlsToHam.js.map +0 -1
- package/dist/mapper/hls/mapHlsToHam/subtitleGroupsToSwitchingSets.d.ts +0 -4
- package/dist/mapper/hls/mapHlsToHam/subtitleGroupsToSwitchingSets.d.ts.map +0 -1
- package/dist/mapper/hls/mapHlsToHam/subtitleGroupsToSwitchingSets.js +0 -35
- package/dist/mapper/hls/mapHlsToHam/subtitleGroupsToSwitchingSets.js.map +0 -1
- package/dist/mapper/hls/mapHlsToHam/utils/formatSegments.d.ts +0 -14
- package/dist/mapper/hls/mapHlsToHam/utils/formatSegments.d.ts.map +0 -1
- package/dist/mapper/hls/mapHlsToHam/utils/formatSegments.js +0 -23
- package/dist/mapper/hls/mapHlsToHam/utils/formatSegments.js.map +0 -1
- package/dist/mapper/hls/mapHlsToHam/utils/getByterange.d.ts +0 -13
- package/dist/mapper/hls/mapHlsToHam/utils/getByterange.d.ts.map +0 -1
- package/dist/mapper/hls/mapHlsToHam/utils/getByterange.js +0 -17
- package/dist/mapper/hls/mapHlsToHam/utils/getByterange.js.map +0 -1
- package/dist/mapper/hls/mapHlsToHam/utils/getCodec.d.ts +0 -13
- package/dist/mapper/hls/mapHlsToHam/utils/getCodec.d.ts.map +0 -1
- package/dist/mapper/hls/mapHlsToHam/utils/getCodec.js +0 -31
- package/dist/mapper/hls/mapHlsToHam/utils/getCodec.js.map +0 -1
- package/dist/mapper/hls/mapHlsToHam/utils/getDuration.d.ts +0 -17
- package/dist/mapper/hls/mapHlsToHam/utils/getDuration.d.ts.map +0 -1
- package/dist/mapper/hls/mapHlsToHam/utils/getDuration.js +0 -21
- package/dist/mapper/hls/mapHlsToHam/utils/getDuration.js.map +0 -1
- package/dist/mapper/hls/mapHlsToHam/videoPlaylistsToSwitchingSets.d.ts +0 -5
- package/dist/mapper/hls/mapHlsToHam/videoPlaylistsToSwitchingSets.d.ts.map +0 -1
- package/dist/mapper/hls/mapHlsToHam/videoPlaylistsToSwitchingSets.js +0 -46
- package/dist/mapper/hls/mapHlsToHam/videoPlaylistsToSwitchingSets.js.map +0 -1
- package/dist/services/converters/dashToHam.d.ts +0 -20
- package/dist/services/converters/dashToHam.d.ts.map +0 -1
- package/dist/services/converters/dashToHam.js +0 -25
- package/dist/services/converters/dashToHam.js.map +0 -1
- package/dist/services/converters/hamToDash.d.ts +0 -21
- package/dist/services/converters/hamToDash.d.ts.map +0 -1
- package/dist/services/converters/hamToDash.js +0 -25
- package/dist/services/converters/hamToDash.js.map +0 -1
- package/dist/services/converters/hamToHls.d.ts +0 -21
- package/dist/services/converters/hamToHls.d.ts.map +0 -1
- package/dist/services/converters/hamToHls.js +0 -25
- package/dist/services/converters/hamToHls.js.map +0 -1
- package/dist/services/converters/hlsToHam.d.ts +0 -21
- package/dist/services/converters/hlsToHam.d.ts.map +0 -1
- package/dist/services/converters/hlsToHam.js +0 -33
- package/dist/services/converters/hlsToHam.js.map +0 -1
- package/dist/services/getters/getTracksFromPresentation.d.ts +0 -13
- package/dist/services/getters/getTracksFromPresentation.d.ts.map +0 -1
- package/dist/services/getters/getTracksFromPresentation.js +0 -15
- package/dist/services/getters/getTracksFromPresentation.js.map +0 -1
- package/dist/services/getters/getTracksFromSelectionSet.d.ts +0 -13
- package/dist/services/getters/getTracksFromSelectionSet.d.ts.map +0 -1
- package/dist/services/getters/getTracksFromSelectionSet.js +0 -15
- package/dist/services/getters/getTracksFromSelectionSet.js.map +0 -1
- package/dist/services/getters/getTracksFromSwitchingSet.d.ts +0 -13
- package/dist/services/getters/getTracksFromSwitchingSet.d.ts.map +0 -1
- package/dist/services/getters/getTracksFromSwitchingSet.js +0 -14
- package/dist/services/getters/getTracksFromSwitchingSet.js.map +0 -1
- package/dist/services/validators/validatePresentation.d.ts +0 -29
- package/dist/services/validators/validatePresentation.d.ts.map +0 -1
- package/dist/services/validators/validatePresentation.js +0 -36
- package/dist/services/validators/validatePresentation.js.map +0 -1
- package/dist/services/validators/validateSegment.d.ts +0 -18
- package/dist/services/validators/validateSegment.d.ts.map +0 -1
- package/dist/services/validators/validateSegment.js +0 -33
- package/dist/services/validators/validateSegment.js.map +0 -1
- package/dist/services/validators/validateSegments.d.ts +0 -27
- package/dist/services/validators/validateSegments.d.ts.map +0 -1
- package/dist/services/validators/validateSegments.js +0 -35
- package/dist/services/validators/validateSegments.js.map +0 -1
- package/dist/services/validators/validateSelectionSet.d.ts +0 -31
- package/dist/services/validators/validateSelectionSet.d.ts.map +0 -1
- package/dist/services/validators/validateSelectionSet.js +0 -44
- package/dist/services/validators/validateSelectionSet.js.map +0 -1
- package/dist/services/validators/validateSelectionSets.d.ts +0 -28
- package/dist/services/validators/validateSelectionSets.d.ts.map +0 -1
- package/dist/services/validators/validateSelectionSets.js +0 -36
- package/dist/services/validators/validateSelectionSets.js.map +0 -1
- package/dist/services/validators/validateSwitchingSet.d.ts +0 -31
- package/dist/services/validators/validateSwitchingSet.d.ts.map +0 -1
- package/dist/services/validators/validateSwitchingSet.js +0 -44
- package/dist/services/validators/validateSwitchingSet.js.map +0 -1
- package/dist/services/validators/validateSwitchingSets.d.ts +0 -28
- package/dist/services/validators/validateSwitchingSets.d.ts.map +0 -1
- package/dist/services/validators/validateSwitchingSets.js +0 -36
- package/dist/services/validators/validateSwitchingSets.js.map +0 -1
- package/dist/services/validators/validateTrack.d.ts +0 -32
- package/dist/services/validators/validateTrack.d.ts.map +0 -1
- package/dist/services/validators/validateTrack.js +0 -140
- package/dist/services/validators/validateTrack.js.map +0 -1
- package/dist/services/validators/validateTracks.d.ts +0 -28
- package/dist/services/validators/validateTracks.d.ts.map +0 -1
- package/dist/services/validators/validateTracks.js +0 -47
- package/dist/services/validators/validateTracks.js.map +0 -1
- package/dist/tsconfig.tsbuildinfo +0 -1
- package/dist/types/Validation.d.ts +0 -10
- package/dist/types/Validation.d.ts.map +0 -1
- package/dist/types/Validation.js +0 -2
- package/dist/types/Validation.js.map +0 -1
- package/dist/types/manifest/Manifest.d.ts +0 -14
- package/dist/types/manifest/Manifest.d.ts.map +0 -1
- package/dist/types/manifest/Manifest.js +0 -2
- package/dist/types/manifest/Manifest.js.map +0 -1
- package/dist/types/manifest/ManifestFormat.d.ts +0 -7
- package/dist/types/manifest/ManifestFormat.d.ts.map +0 -1
- package/dist/types/manifest/ManifestFormat.js +0 -2
- package/dist/types/manifest/ManifestFormat.js.map +0 -1
- package/dist/types/mapper/dash/AdaptationSet.d.ts +0 -41
- package/dist/types/mapper/dash/AdaptationSet.d.ts.map +0 -1
- package/dist/types/mapper/dash/AdaptationSet.js +0 -2
- package/dist/types/mapper/dash/AdaptationSet.js.map +0 -1
- package/dist/types/mapper/dash/AudioChannelConfiguration.d.ts +0 -12
- package/dist/types/mapper/dash/AudioChannelConfiguration.d.ts.map +0 -1
- package/dist/types/mapper/dash/AudioChannelConfiguration.js +0 -2
- package/dist/types/mapper/dash/AudioChannelConfiguration.js.map +0 -1
- package/dist/types/mapper/dash/ContentComponent.d.ts +0 -11
- package/dist/types/mapper/dash/ContentComponent.d.ts.map +0 -1
- package/dist/types/mapper/dash/ContentComponent.js +0 -2
- package/dist/types/mapper/dash/ContentComponent.js.map +0 -1
- package/dist/types/mapper/dash/DashManifest.d.ts +0 -20
- package/dist/types/mapper/dash/DashManifest.d.ts.map +0 -1
- package/dist/types/mapper/dash/DashManifest.js +0 -2
- package/dist/types/mapper/dash/DashManifest.js.map +0 -1
- package/dist/types/mapper/dash/Initialization.d.ts +0 -12
- package/dist/types/mapper/dash/Initialization.d.ts.map +0 -1
- package/dist/types/mapper/dash/Initialization.js +0 -2
- package/dist/types/mapper/dash/Initialization.js.map +0 -1
- package/dist/types/mapper/dash/Period.d.ts +0 -15
- package/dist/types/mapper/dash/Period.d.ts.map +0 -1
- package/dist/types/mapper/dash/Period.js +0 -2
- package/dist/types/mapper/dash/Period.js.map +0 -1
- package/dist/types/mapper/dash/Representation.d.ts +0 -30
- package/dist/types/mapper/dash/Representation.d.ts.map +0 -1
- package/dist/types/mapper/dash/Representation.js +0 -2
- package/dist/types/mapper/dash/Representation.js.map +0 -1
- package/dist/types/mapper/dash/Role.d.ts +0 -12
- package/dist/types/mapper/dash/Role.d.ts.map +0 -1
- package/dist/types/mapper/dash/Role.js +0 -2
- package/dist/types/mapper/dash/Role.js.map +0 -1
- package/dist/types/mapper/dash/SegmentBase.d.ts +0 -15
- package/dist/types/mapper/dash/SegmentBase.d.ts.map +0 -1
- package/dist/types/mapper/dash/SegmentBase.js +0 -2
- package/dist/types/mapper/dash/SegmentBase.js.map +0 -1
- package/dist/types/mapper/dash/SegmentList.d.ts +0 -16
- package/dist/types/mapper/dash/SegmentList.d.ts.map +0 -1
- package/dist/types/mapper/dash/SegmentList.js +0 -2
- package/dist/types/mapper/dash/SegmentList.js.map +0 -1
- package/dist/types/mapper/dash/SegmentTemplate.d.ts +0 -17
- package/dist/types/mapper/dash/SegmentTemplate.d.ts.map +0 -1
- package/dist/types/mapper/dash/SegmentTemplate.js +0 -2
- package/dist/types/mapper/dash/SegmentTemplate.js.map +0 -1
- package/dist/types/mapper/dash/SegmentUrl.d.ts +0 -11
- package/dist/types/mapper/dash/SegmentUrl.d.ts.map +0 -1
- package/dist/types/mapper/dash/SegmentUrl.js +0 -2
- package/dist/types/mapper/dash/SegmentUrl.js.map +0 -1
- package/dist/types/mapper/hls/Byterange.d.ts +0 -11
- package/dist/types/mapper/hls/Byterange.d.ts.map +0 -1
- package/dist/types/mapper/hls/Byterange.js +0 -2
- package/dist/types/mapper/hls/Byterange.js.map +0 -1
- package/dist/types/mapper/hls/HlsManifest.d.ts +0 -15
- package/dist/types/mapper/hls/HlsManifest.d.ts.map +0 -1
- package/dist/types/mapper/hls/HlsManifest.js +0 -2
- package/dist/types/mapper/hls/HlsManifest.js.map +0 -1
- package/dist/types/mapper/hls/MediaGroups.d.ts +0 -22
- package/dist/types/mapper/hls/MediaGroups.d.ts.map +0 -1
- package/dist/types/mapper/hls/MediaGroups.js +0 -2
- package/dist/types/mapper/hls/MediaGroups.js.map +0 -1
- package/dist/types/mapper/hls/Playlist.d.ts +0 -18
- package/dist/types/mapper/hls/Playlist.d.ts.map +0 -1
- package/dist/types/mapper/hls/Playlist.js +0 -2
- package/dist/types/mapper/hls/Playlist.js.map +0 -1
- package/dist/types/mapper/hls/SegmentHls.d.ts +0 -18
- package/dist/types/mapper/hls/SegmentHls.d.ts.map +0 -1
- package/dist/types/mapper/hls/SegmentHls.js +0 -2
- package/dist/types/mapper/hls/SegmentHls.js.map +0 -1
- package/dist/types/model/AlignedSwitchingSet.d.ts +0 -10
- package/dist/types/model/AlignedSwitchingSet.d.ts.map +0 -1
- package/dist/types/model/AlignedSwitchingSet.js +0 -2
- package/dist/types/model/AlignedSwitchingSet.js.map +0 -1
- package/dist/types/model/AudioTrack.d.ts +0 -17
- package/dist/types/model/AudioTrack.d.ts.map +0 -1
- package/dist/types/model/AudioTrack.js +0 -2
- package/dist/types/model/AudioTrack.js.map +0 -1
- package/dist/types/model/FrameRate.d.ts +0 -14
- package/dist/types/model/FrameRate.d.ts.map +0 -1
- package/dist/types/model/FrameRate.js +0 -11
- package/dist/types/model/FrameRate.js.map +0 -1
- package/dist/types/model/Ham.d.ts +0 -11
- package/dist/types/model/Ham.d.ts.map +0 -1
- package/dist/types/model/Ham.js +0 -2
- package/dist/types/model/Ham.js.map +0 -1
- package/dist/types/model/Presentation.d.ts +0 -13
- package/dist/types/model/Presentation.d.ts.map +0 -1
- package/dist/types/model/Presentation.js +0 -2
- package/dist/types/model/Presentation.js.map +0 -1
- package/dist/types/model/Segment.d.ts +0 -11
- package/dist/types/model/Segment.d.ts.map +0 -1
- package/dist/types/model/Segment.js +0 -2
- package/dist/types/model/Segment.js.map +0 -1
- package/dist/types/model/SelectionSet.d.ts +0 -13
- package/dist/types/model/SelectionSet.d.ts.map +0 -1
- package/dist/types/model/SelectionSet.js +0 -2
- package/dist/types/model/SelectionSet.js.map +0 -1
- package/dist/types/model/SwitchingSet.d.ts +0 -11
- package/dist/types/model/SwitchingSet.d.ts.map +0 -1
- package/dist/types/model/SwitchingSet.js +0 -2
- package/dist/types/model/SwitchingSet.js.map +0 -1
- package/dist/types/model/TextTrack.d.ts +0 -8
- package/dist/types/model/TextTrack.d.ts.map +0 -1
- package/dist/types/model/TextTrack.js +0 -2
- package/dist/types/model/TextTrack.js.map +0 -1
- package/dist/types/model/Track.d.ts +0 -32
- package/dist/types/model/Track.d.ts.map +0 -1
- package/dist/types/model/Track.js +0 -2
- package/dist/types/model/Track.js.map +0 -1
- package/dist/types/model/TrackType.d.ts +0 -8
- package/dist/types/model/TrackType.d.ts.map +0 -1
- package/dist/types/model/TrackType.js +0 -2
- package/dist/types/model/TrackType.js.map +0 -1
- package/dist/types/model/VideoTrack.d.ts +0 -23
- package/dist/types/model/VideoTrack.d.ts.map +0 -1
- package/dist/types/model/VideoTrack.js +0 -2
- package/dist/types/model/VideoTrack.js.map +0 -1
- package/dist/utils/constants.d.ts +0 -16
- package/dist/utils/constants.d.ts.map +0 -1
- package/dist/utils/constants.js +0 -21
- package/dist/utils/constants.js.map +0 -1
- package/dist/utils/dash/iso8601DurationToNumber.d.ts +0 -2
- package/dist/utils/dash/iso8601DurationToNumber.d.ts.map +0 -1
- package/dist/utils/dash/iso8601DurationToNumber.js +0 -17
- package/dist/utils/dash/iso8601DurationToNumber.js.map +0 -1
- package/dist/utils/dash/numberToIso8601Duration.d.ts +0 -2
- package/dist/utils/dash/numberToIso8601Duration.d.ts.map +0 -1
- package/dist/utils/dash/numberToIso8601Duration.js +0 -13
- package/dist/utils/dash/numberToIso8601Duration.js.map +0 -1
- package/dist/utils/dash/parseDashManifest.d.ts +0 -22
- package/dist/utils/dash/parseDashManifest.d.ts.map +0 -1
- package/dist/utils/dash/parseDashManifest.js +0 -24
- package/dist/utils/dash/parseDashManifest.js.map +0 -1
- package/dist/utils/dash/serializeDashManifest.d.ts +0 -18
- package/dist/utils/dash/serializeDashManifest.d.ts.map +0 -1
- package/dist/utils/dash/serializeDashManifest.js +0 -20
- package/dist/utils/dash/serializeDashManifest.js.map +0 -1
- package/dist/utils/hls/parseHlsManifest.d.ts +0 -18
- package/dist/utils/hls/parseHlsManifest.d.ts.map +0 -1
- package/dist/utils/hls/parseHlsManifest.js +0 -24
- package/dist/utils/hls/parseHlsManifest.js.map +0 -1
- package/dist/utils/manifest/addMetadataToDash.d.ts +0 -4
- package/dist/utils/manifest/addMetadataToDash.d.ts.map +0 -1
- package/dist/utils/manifest/addMetadataToDash.js +0 -15
- package/dist/utils/manifest/addMetadataToDash.js.map +0 -1
- package/dist/utils/manifest/addMetadataToHls.d.ts +0 -3
- package/dist/utils/manifest/addMetadataToHls.d.ts.map +0 -1
- package/dist/utils/manifest/addMetadataToHls.js +0 -15
- package/dist/utils/manifest/addMetadataToHls.js.map +0 -1
- package/dist/utils/manifest/getMetadata.d.ts +0 -3
- package/dist/utils/manifest/getMetadata.d.ts.map +0 -1
- package/dist/utils/manifest/getMetadata.js +0 -5
- package/dist/utils/manifest/getMetadata.js.map +0 -1
package/dist/index.js
CHANGED
|
@@ -1,20 +1,1823 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
1
|
+
//#region src/mapper/dash/mapDashToHam/mapSegmentBase.ts
|
|
2
|
+
/**
|
|
3
|
+
* @internal
|
|
4
|
+
*
|
|
5
|
+
* Maps SegmentBase from dash to Segment list from ham.
|
|
6
|
+
*
|
|
7
|
+
* @param representation - Representation to get the SegmentBase from
|
|
8
|
+
* @param duration - Duration of the segment
|
|
9
|
+
* @returns list of ham segments
|
|
10
|
+
*/
|
|
11
|
+
function mapSegmentBase(representation, duration) {
|
|
12
|
+
return representation.SegmentBase.map((segment) => {
|
|
13
|
+
return {
|
|
14
|
+
duration,
|
|
15
|
+
url: representation.BaseURL[0] ?? "",
|
|
16
|
+
byteRange: segment.$.indexRange
|
|
17
|
+
};
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
//#endregion
|
|
22
|
+
//#region src/mapper/dash/mapDashToHam/utils/calculateDuration.ts
|
|
23
|
+
/**
|
|
24
|
+
* @internal
|
|
25
|
+
*
|
|
26
|
+
* Calculates the duration of a segment.
|
|
27
|
+
*
|
|
28
|
+
* segmentDuration = duration / timescale
|
|
29
|
+
*
|
|
30
|
+
* @param duration - Duration of the segment
|
|
31
|
+
* @param timescale - Timescale of the segment
|
|
32
|
+
* @returns Segment duration
|
|
33
|
+
*/
|
|
34
|
+
function calculateDuration(duration, timescale) {
|
|
35
|
+
if (!duration || !timescale) return 1;
|
|
36
|
+
return +(duration ?? 1) / +(timescale ?? 1);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
//#endregion
|
|
40
|
+
//#region src/mapper/dash/mapDashToHam/mapSegmentList.ts
|
|
41
|
+
/**
|
|
42
|
+
* @internal
|
|
43
|
+
*
|
|
44
|
+
* Maps SegmentList from dash to Segment list from ham.
|
|
45
|
+
*
|
|
46
|
+
* @param segmentList - SegmentList list from dash
|
|
47
|
+
* @returns list of ham segments
|
|
48
|
+
*/
|
|
49
|
+
function mapSegmentList(segmentList) {
|
|
50
|
+
const segments = [];
|
|
51
|
+
segmentList.map((segment) => {
|
|
52
|
+
if (segment.SegmentURL) return segment.SegmentURL.forEach((segmentURL) => {
|
|
53
|
+
segments.push({
|
|
54
|
+
duration: calculateDuration(segment.$.duration, segment.$.timescale),
|
|
55
|
+
url: segmentURL.$.media ?? ""
|
|
56
|
+
});
|
|
57
|
+
});
|
|
58
|
+
});
|
|
59
|
+
return segments;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
//#endregion
|
|
63
|
+
//#region src/mapper/dash/mapDashToHam/utils/getNumberOfSegments.ts
|
|
64
|
+
/**
|
|
65
|
+
* @internal
|
|
66
|
+
*
|
|
67
|
+
* Calculates the number of segments that a track has to use SegmentTemplate.
|
|
68
|
+
*
|
|
69
|
+
* Equation used:
|
|
70
|
+
* segments = total duration / (segment duration / timescale)
|
|
71
|
+
*
|
|
72
|
+
* **This equation might be wrong, please double-check it**
|
|
73
|
+
*
|
|
74
|
+
* @param segmentTemplate - SegmentTemplate object
|
|
75
|
+
* @param duration - Total duration of the content
|
|
76
|
+
* @returns Number of segments
|
|
77
|
+
*/
|
|
78
|
+
function getNumberOfSegments(segmentTemplate, duration) {
|
|
79
|
+
return Math.round(duration / calculateDuration(segmentTemplate.$.duration, segmentTemplate.$.timescale));
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
//#endregion
|
|
83
|
+
//#region src/mapper/dash/mapDashToHam/utils/getUrlFromTemplate.ts
|
|
84
|
+
/**
|
|
85
|
+
* @internal
|
|
86
|
+
*
|
|
87
|
+
* Create the url from a segment template.
|
|
88
|
+
*
|
|
89
|
+
* Searches for substrings with the format `$value$` and replaces it with the correct value.
|
|
90
|
+
* - RepresentationID: id of the representation
|
|
91
|
+
* - Number: id of the segment. `%0Xd` defines the number `X` of digits it needs to have
|
|
92
|
+
*
|
|
93
|
+
* @param representation - Representation of the template
|
|
94
|
+
* @param segmentTemplate - Segment template
|
|
95
|
+
* @param segmentId - Segment id
|
|
96
|
+
* @returns url from the segment template
|
|
97
|
+
*/
|
|
98
|
+
function getUrlFromTemplate(representation, segmentTemplate, segmentId) {
|
|
99
|
+
return segmentTemplate.$.media.replace(/\$(.*?)\$/g, (match) => {
|
|
100
|
+
if (match.includes("RepresentationID")) return representation.$.id;
|
|
101
|
+
/**
|
|
102
|
+
* Number with 4 digits e.g: 0001
|
|
103
|
+
*/
|
|
104
|
+
if (match.includes("Number%04d")) return segmentId.toString().padStart(4, "0");
|
|
105
|
+
if (match.includes("Number")) return segmentId;
|
|
106
|
+
console.error(`Unknown property ${match} from the SegmentTemplate on representation ${representation.$.id}`);
|
|
107
|
+
return match;
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
//#endregion
|
|
112
|
+
//#region src/mapper/dash/mapDashToHam/mapSegmentTemplate.ts
|
|
113
|
+
/**
|
|
114
|
+
* @internal
|
|
115
|
+
*
|
|
116
|
+
* Maps SegmentTemplate from dash to Segment list from ham.
|
|
117
|
+
*
|
|
118
|
+
* @param representation - Representation to generate the urls
|
|
119
|
+
* @param duration - Duration of the segments
|
|
120
|
+
* @param segmentTemplate - SegmentTemplate to get the properties from
|
|
121
|
+
* @returns list of ham segments
|
|
122
|
+
*/
|
|
123
|
+
function mapSegmentTemplate(representation, duration, segmentTemplate) {
|
|
124
|
+
const numberOfSegments = getNumberOfSegments(segmentTemplate, duration);
|
|
125
|
+
const init = +(segmentTemplate.$.startNumber ?? 0);
|
|
126
|
+
const segments = [];
|
|
127
|
+
for (let id = init; id < numberOfSegments + init; id++) segments.push({
|
|
128
|
+
duration: calculateDuration(segmentTemplate.$.duration, segmentTemplate.$.timescale),
|
|
129
|
+
url: getUrlFromTemplate(representation, segmentTemplate, id)
|
|
130
|
+
});
|
|
131
|
+
return segments;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
//#endregion
|
|
135
|
+
//#region src/mapper/dash/mapDashToHam/mapSegments.ts
|
|
136
|
+
/**
|
|
137
|
+
* @internal
|
|
138
|
+
*
|
|
139
|
+
* Maps dash segments to ham segment.
|
|
140
|
+
*
|
|
141
|
+
* Checks the type of dash segments used to map them accordingly.
|
|
142
|
+
* @see mapSegmentBase
|
|
143
|
+
* @see mapSegmentList
|
|
144
|
+
* @see mapSegmentTemplate
|
|
145
|
+
*
|
|
146
|
+
* @param adaptationSet - AdaptationSet to get the segments from
|
|
147
|
+
* @param representation - Representation to get the segments from
|
|
148
|
+
* @param duration - Duration of the segments
|
|
149
|
+
* @returns list of ham segments
|
|
150
|
+
*/
|
|
151
|
+
function mapSegments(adaptationSet, representation, duration) {
|
|
152
|
+
const segmentTemplate = adaptationSet.SegmentTemplate?.at(0) ?? representation.SegmentTemplate?.at(0);
|
|
153
|
+
const segmentList = adaptationSet.SegmentList ?? representation.SegmentList;
|
|
154
|
+
if (representation.SegmentBase) return mapSegmentBase(representation, duration);
|
|
155
|
+
else if (segmentList) return mapSegmentList(segmentList);
|
|
156
|
+
else if (segmentTemplate) return mapSegmentTemplate(representation, duration, segmentTemplate);
|
|
157
|
+
else {
|
|
158
|
+
console.error(`Representation ${representation.$.id} has no segments`);
|
|
159
|
+
return [];
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
//#endregion
|
|
164
|
+
//#region src/mapper/dash/mapDashToHam/utils/getChannels.ts
|
|
165
|
+
/**
|
|
166
|
+
* @internal
|
|
167
|
+
*
|
|
168
|
+
* Get the channels value (audio). It can be present on adaptationSet or representation.
|
|
169
|
+
*
|
|
170
|
+
* @param adaptationSet - AdaptationSet to try to get the channels from
|
|
171
|
+
* @param representation - Representation to try to get the channels from
|
|
172
|
+
* @returns Channels value
|
|
173
|
+
*/
|
|
174
|
+
function getChannels(adaptationSet, representation) {
|
|
175
|
+
const channels = +(adaptationSet.AudioChannelConfiguration?.at(0)?.$.value ?? representation.AudioChannelConfiguration?.at(0)?.$.value ?? 0);
|
|
176
|
+
if (!channels) console.error(`Representation ${representation.$.id} has no channels`);
|
|
177
|
+
return channels;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
//#endregion
|
|
181
|
+
//#region src/mapper/dash/mapDashToHam/utils/getCodec.ts
|
|
182
|
+
/**
|
|
183
|
+
* @internal
|
|
184
|
+
*
|
|
185
|
+
* Get the codec value (video and audio). It can be present on adaptationSet or representation.
|
|
186
|
+
*
|
|
187
|
+
* @param adaptationSet - AdaptationSet to try to get the codec from
|
|
188
|
+
* @param representation - Representation to try to get the codec from
|
|
189
|
+
* @returns Content codec
|
|
190
|
+
*/
|
|
191
|
+
function getCodec(adaptationSet, representation) {
|
|
192
|
+
const codec = representation.$.codecs ?? adaptationSet.$.codecs ?? "";
|
|
193
|
+
if (!codec) console.error(`Representation ${representation.$.id} has no codecs`);
|
|
194
|
+
return codec;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
//#endregion
|
|
198
|
+
//#region src/mapper/dash/mapDashToHam/utils/getContentType.ts
|
|
199
|
+
/**
|
|
200
|
+
* @internal
|
|
201
|
+
*
|
|
202
|
+
* Get the type of the content. It can be obtained directly from AdaptationSet or Representation
|
|
203
|
+
* or can be inferred with the existing properties.
|
|
204
|
+
*
|
|
205
|
+
* @param adaptationSet - AdaptationSet to get the type from
|
|
206
|
+
* @param representation - Representation to get the type from
|
|
207
|
+
* @returns type of the content
|
|
208
|
+
*/
|
|
209
|
+
function getContentType(adaptationSet, representation) {
|
|
210
|
+
if (adaptationSet.$.contentType) return adaptationSet.$.contentType;
|
|
211
|
+
if (adaptationSet.ContentComponent?.at(0)) return adaptationSet.ContentComponent.at(0).$.contentType;
|
|
212
|
+
if (adaptationSet.$.mimeType || representation?.$.mimeType) {
|
|
213
|
+
const type = adaptationSet.$.mimeType?.split("/")[0] || representation?.$.mimeType?.split("/")[0];
|
|
214
|
+
if (type === "audio" || type === "video" || type === "text") return type;
|
|
215
|
+
if (type === "application") return "text";
|
|
216
|
+
}
|
|
217
|
+
if (adaptationSet.$.maxHeight) return "video";
|
|
218
|
+
const adaptationRef = adaptationSet.$.id ?? `group: ${adaptationSet.$.group}, lang: ${adaptationSet.$.lang}`;
|
|
219
|
+
console.error(`Could not find contentType from adaptationSet ${adaptationRef}`);
|
|
220
|
+
console.info("Using \"text\" as default contentType");
|
|
221
|
+
return "text";
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
//#endregion
|
|
225
|
+
//#region src/utils/constants.ts
|
|
226
|
+
const TIMESCALE_48000 = 48e3;
|
|
227
|
+
const VIDEO_SAMPLE_RATE = 9e4;
|
|
228
|
+
const TEXT_SAMPLE_RATE = 1e3;
|
|
229
|
+
const FRAME_RATE_NUMERATOR_30 = 30;
|
|
230
|
+
const WHITE_SPACE = " ";
|
|
231
|
+
const WHITE_SPACE_ENCODED = "%20";
|
|
232
|
+
const HYPHEN_MINUS_SEPARATOR = "-";
|
|
233
|
+
const AT_SEPARATOR = "@";
|
|
234
|
+
const FRAME_RATE_SEPARATOR = "/";
|
|
235
|
+
const NUMERATOR = 0;
|
|
236
|
+
const DENOMINATOR = 1;
|
|
237
|
+
const ZERO = 0;
|
|
238
|
+
|
|
239
|
+
//#endregion
|
|
240
|
+
//#region src/mapper/dash/mapDashToHam/utils/getFrameRate.ts
|
|
241
|
+
/**
|
|
242
|
+
* @internal
|
|
243
|
+
*
|
|
244
|
+
* Get the frame rate from a dash manifest.
|
|
245
|
+
*
|
|
246
|
+
* This functions assumes the adaptationSet and representation set are type video
|
|
247
|
+
*
|
|
248
|
+
* @param adaptationSet - To try to get the frameRate from
|
|
249
|
+
* @param representation - To try to get the frameRate from
|
|
250
|
+
* @returns object containing numerator and denominator
|
|
251
|
+
*/
|
|
252
|
+
function getFrameRate(adaptationSet, representation) {
|
|
253
|
+
const frameRateDash = representation.$.frameRate ?? adaptationSet.$.frameRate ?? "";
|
|
254
|
+
if (!frameRateDash) console.error(`Representation ${representation.$.id} has no frame rate`);
|
|
255
|
+
const frameRate = frameRateDash.split(FRAME_RATE_SEPARATOR);
|
|
256
|
+
const frameRateNumerator = parseInt(frameRate.at(NUMERATOR) ?? "");
|
|
257
|
+
const frameRateDenominator = parseInt(frameRate.at(DENOMINATOR) ?? "");
|
|
258
|
+
return {
|
|
259
|
+
frameRateNumerator: isNaN(frameRateNumerator) ? FRAME_RATE_NUMERATOR_30 : frameRateNumerator,
|
|
260
|
+
frameRateDenominator: isNaN(frameRateDenominator) ? ZERO : frameRateDenominator
|
|
261
|
+
};
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
//#endregion
|
|
265
|
+
//#region src/mapper/dash/mapDashToHam/utils/getGroup.ts
|
|
266
|
+
/**
|
|
267
|
+
* @internal
|
|
268
|
+
*/
|
|
269
|
+
function getGroup(adaptationSet) {
|
|
270
|
+
return adaptationSet.$.group ?? getContentType(adaptationSet);
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
//#endregion
|
|
274
|
+
//#region src/mapper/dash/mapDashToHam/utils/getLanguage.ts
|
|
275
|
+
/**
|
|
276
|
+
* @internal
|
|
277
|
+
*
|
|
278
|
+
* Get the language from an adaptation set.
|
|
279
|
+
*
|
|
280
|
+
* @param adaptationSet - AdaptationSet to get the language from
|
|
281
|
+
* @returns language of the content
|
|
282
|
+
*/
|
|
283
|
+
function getLanguage(adaptationSet) {
|
|
284
|
+
let language = adaptationSet.$.lang;
|
|
285
|
+
if (!language) {
|
|
286
|
+
console.info(`AdaptationSet ${adaptationSet.$.id} has no lang, using "und" as default`);
|
|
287
|
+
language = "und";
|
|
288
|
+
}
|
|
289
|
+
return language;
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
//#endregion
|
|
293
|
+
//#region src/mapper/dash/mapDashToHam/utils/getPresentationId.ts
|
|
294
|
+
/**
|
|
295
|
+
* @internal
|
|
296
|
+
*
|
|
297
|
+
* Generates a presentation id. It uses the period id as default or creates one
|
|
298
|
+
* if none is present.
|
|
299
|
+
*
|
|
300
|
+
* @param period - Period to try to get the id from
|
|
301
|
+
* @param duration - Duration of the content
|
|
302
|
+
* @returns Presentation id
|
|
303
|
+
*/
|
|
304
|
+
function getPresentationId(period, duration) {
|
|
305
|
+
return period.$.id ?? `presentation-id-${duration}`;
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
//#endregion
|
|
309
|
+
//#region src/mapper/dash/mapDashToHam/utils/getSampleRate.ts
|
|
310
|
+
/**
|
|
311
|
+
* @internal
|
|
312
|
+
*
|
|
313
|
+
* Get sample rate (audio).
|
|
314
|
+
*
|
|
315
|
+
* @param adaptationSet - AdaptationSet to try to get the sampleRate from
|
|
316
|
+
* @param representation - Representation to try to get the sampleRate from
|
|
317
|
+
* @returns Sample rate. In case it is not presents, it returns 0.
|
|
318
|
+
*/
|
|
319
|
+
function getSampleRate(adaptationSet, representation) {
|
|
320
|
+
const sampleRate = +(representation.$.audioSamplingRate ?? adaptationSet.$.audioSamplingRate ?? 0);
|
|
321
|
+
if (!sampleRate) console.error(`Representation ${representation.$.id} has no audioSamplingRate`);
|
|
322
|
+
return sampleRate;
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
//#endregion
|
|
326
|
+
//#region src/mapper/dash/mapDashToHam/utils/getSar.ts
|
|
327
|
+
/**
|
|
328
|
+
* @internal
|
|
329
|
+
*
|
|
330
|
+
* Get the sar value. It can be present on adaptationSet or representation.
|
|
331
|
+
*
|
|
332
|
+
* @param adaptationSet - AdaptationSet to try to get the sar from
|
|
333
|
+
* @param representation - AdaptationSet to try to get the sar from
|
|
334
|
+
* @returns sar value. In case it is not present, returns empty string.
|
|
335
|
+
*/
|
|
336
|
+
function getSar(adaptationSet, representation) {
|
|
337
|
+
const sar = representation.$.sar ?? adaptationSet.$.sar ?? "";
|
|
338
|
+
if (!sar) console.error(`Representation ${representation.$.id} has no sar`);
|
|
339
|
+
return sar;
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
//#endregion
|
|
343
|
+
//#region src/mapper/dash/mapDashToHam/utils/getTrackDuration.ts
|
|
344
|
+
/**
|
|
345
|
+
* @internal
|
|
346
|
+
*
|
|
347
|
+
* Calculate the duration of a track.
|
|
348
|
+
*
|
|
349
|
+
* This is calculated using the sum of the duration of all the segments from the
|
|
350
|
+
* track.
|
|
351
|
+
*
|
|
352
|
+
* An alternative to this could be number of segments * duration of a segment.
|
|
353
|
+
*
|
|
354
|
+
* @param segments - Segments to calculate the sum of the durations
|
|
355
|
+
* @returns Duration of the track
|
|
356
|
+
*/
|
|
357
|
+
function getTrackDuration(segments) {
|
|
358
|
+
return segments.reduce((acc, segment) => {
|
|
359
|
+
return acc + segment.duration;
|
|
360
|
+
}, 0);
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
//#endregion
|
|
364
|
+
//#region src/mapper/dash/mapHamToDash/utils/getTimescale.ts
|
|
365
|
+
/**
|
|
366
|
+
* @internal
|
|
367
|
+
*
|
|
368
|
+
* This function tries to recreate the timescale value.
|
|
369
|
+
*
|
|
370
|
+
* This value is not stored on the ham object, so it is not possible (for now)
|
|
371
|
+
* to get the original one.
|
|
372
|
+
*
|
|
373
|
+
* Just the audio tracks have this value stored on the `sampleRate` key.
|
|
374
|
+
*
|
|
375
|
+
* @param track - Track to get the timescale from
|
|
376
|
+
* @returns Timescale in numbers
|
|
377
|
+
*/
|
|
378
|
+
function getTimescale(track) {
|
|
379
|
+
if (track?.type === "audio") {
|
|
380
|
+
const audioTrack = track;
|
|
381
|
+
return audioTrack.sampleRate !== 0 ? audioTrack.sampleRate : TIMESCALE_48000;
|
|
382
|
+
}
|
|
383
|
+
if (track?.type === "video") return VIDEO_SAMPLE_RATE;
|
|
384
|
+
if (track?.type === "text") return TEXT_SAMPLE_RATE;
|
|
385
|
+
return VIDEO_SAMPLE_RATE;
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
//#endregion
|
|
389
|
+
//#region src/mapper/hls/mapHamToHls/utils/encodeByteRange.ts
|
|
390
|
+
/**
|
|
391
|
+
* @internal
|
|
392
|
+
*
|
|
393
|
+
* Get the byterange in hls format from ham track.
|
|
394
|
+
*
|
|
395
|
+
* @param track - Track to get the byterange from
|
|
396
|
+
* @returns string containing the byterange in the hls format
|
|
397
|
+
*
|
|
398
|
+
* @alpha
|
|
399
|
+
*/
|
|
400
|
+
function encodeByteRange(track) {
|
|
401
|
+
if (track.byteRange) return `BYTERANGE:${track.byteRange.replace(HYPHEN_MINUS_SEPARATOR, AT_SEPARATOR)}\n`;
|
|
402
|
+
else if (track.segments?.at(0)?.byteRange) return `BYTERANGE:0@${Number(track.segments.at(0)?.byteRange?.replace(HYPHEN_MINUS_SEPARATOR, AT_SEPARATOR).split(AT_SEPARATOR)[0]) - 1}\n`;
|
|
403
|
+
return "";
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
//#endregion
|
|
407
|
+
//#region src/mapper/hls/mapHamToHls/utils/getUrlInitialization.ts
|
|
408
|
+
/**
|
|
409
|
+
* @internal
|
|
410
|
+
*
|
|
411
|
+
* Get url initialization from ham track.
|
|
412
|
+
*
|
|
413
|
+
* @param track - Track to get the url initialization from
|
|
414
|
+
* @returns string containing the url initialization in the hls format
|
|
415
|
+
*
|
|
416
|
+
* @alpha
|
|
417
|
+
*/
|
|
418
|
+
function getUrlInitialization(track) {
|
|
419
|
+
return track.urlInitialization?.replaceAll(WHITE_SPACE, WHITE_SPACE_ENCODED) ?? "";
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
//#endregion
|
|
423
|
+
//#region src/mapper/hls/mapHamToHls/utils/getPlaylistData.ts
|
|
424
|
+
/**
|
|
425
|
+
* @internal
|
|
426
|
+
*
|
|
427
|
+
* Get the playlist data in hls format from ham track.
|
|
428
|
+
*
|
|
429
|
+
* @param track - Track to get the playlist data from
|
|
430
|
+
* @returns string containing the playlist data in the hls format
|
|
431
|
+
*
|
|
432
|
+
* @alpha
|
|
433
|
+
*/
|
|
434
|
+
function getPlaylistData(track) {
|
|
435
|
+
return `#EXT-X-MAP:URI="${getUrlInitialization(track)}",${encodeByteRange(track)}\n`;
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
//#endregion
|
|
439
|
+
//#region src/mapper/hls/mapHamToHls/utils/getSegments.ts
|
|
440
|
+
/**
|
|
441
|
+
* @internal
|
|
442
|
+
*
|
|
443
|
+
* Format the ham segments to hls.
|
|
444
|
+
*
|
|
445
|
+
* @param segments - Segments to be formatted
|
|
446
|
+
* @returns string containing the segments in the hls format
|
|
447
|
+
*
|
|
448
|
+
* @alpha
|
|
449
|
+
*/
|
|
450
|
+
function getSegments(segments) {
|
|
451
|
+
return segments.map((segment) => {
|
|
452
|
+
const byteRange = segment.byteRange ? `#EXT-X-BYTERANGE:${segment.byteRange.replace(HYPHEN_MINUS_SEPARATOR, AT_SEPARATOR)}\n` : "";
|
|
453
|
+
const url = segment.url.replaceAll(WHITE_SPACE, WHITE_SPACE_ENCODED);
|
|
454
|
+
return `#EXTINF:${segment.duration},\n${byteRange}\n${url}`;
|
|
455
|
+
}).join("\n");
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
//#endregion
|
|
459
|
+
//#region src/mapper/hls/mapHlsToHam/utils/decodeByteRange.ts
|
|
460
|
+
/**
|
|
461
|
+
* @internal
|
|
462
|
+
*
|
|
463
|
+
* Get byterange from HLS Manifest.
|
|
464
|
+
*
|
|
465
|
+
* @param byteRange - Byterange object containing length and offset
|
|
466
|
+
* @returns string containing the byterange. If byterange is undefined, it returns undefined
|
|
467
|
+
*
|
|
468
|
+
* @alpha
|
|
469
|
+
*/
|
|
470
|
+
function decodeByteRange(byteRange) {
|
|
471
|
+
if (!byteRange) return "";
|
|
472
|
+
return `${byteRange.length}@${byteRange.offset}`;
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
//#endregion
|
|
476
|
+
//#region src/mapper/hls/mapHlsToHam/utils/formatSegments.ts
|
|
477
|
+
/**
|
|
478
|
+
* @internal
|
|
479
|
+
*
|
|
480
|
+
* Format the hls segments into the ham segments.
|
|
481
|
+
*
|
|
482
|
+
* @param segments - List of HLS segments
|
|
483
|
+
* @returns ham formatted list of segments
|
|
484
|
+
*
|
|
485
|
+
* @alpha
|
|
486
|
+
*/
|
|
487
|
+
function formatSegments(segments) {
|
|
488
|
+
return segments?.map((segment) => {
|
|
489
|
+
const byteRange = decodeByteRange(segment?.byterange);
|
|
490
|
+
return {
|
|
491
|
+
duration: segment.duration,
|
|
492
|
+
url: segment.uri,
|
|
493
|
+
...byteRange && { byteRange }
|
|
494
|
+
};
|
|
495
|
+
}) ?? [];
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
//#endregion
|
|
499
|
+
//#region src/mapper/hls/mapHlsToHam/utils/getDuration.ts
|
|
500
|
+
/**
|
|
501
|
+
* @internal
|
|
502
|
+
*
|
|
503
|
+
* Calculate the duration of a track.
|
|
504
|
+
*
|
|
505
|
+
* `target duration * number of segments`
|
|
506
|
+
*
|
|
507
|
+
* @param manifest - Manifest of the track
|
|
508
|
+
* @param segments - Array of segments in a track
|
|
509
|
+
* @returns duration of a track
|
|
510
|
+
*
|
|
511
|
+
* @alpha
|
|
512
|
+
*/
|
|
513
|
+
function getDuration(manifest, segments) {
|
|
514
|
+
if (!manifest?.targetDuration) {
|
|
515
|
+
console.error("Could not calculate duration, manifest is undefined.");
|
|
516
|
+
return null;
|
|
517
|
+
}
|
|
518
|
+
return manifest?.targetDuration * segments.length;
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
//#endregion
|
|
522
|
+
//#region src/mapper/hls/mapHlsToHam/utils/getHlsCodec.ts
|
|
523
|
+
/**
|
|
524
|
+
* @internal
|
|
525
|
+
*
|
|
526
|
+
* Get the codec for a type of content.
|
|
527
|
+
*
|
|
528
|
+
* @param type - Type of the content to get the codecs from
|
|
529
|
+
* @param codecs - String containing multiple codecs separated with commas
|
|
530
|
+
* @returns string containing codec
|
|
531
|
+
*
|
|
532
|
+
* @alpha
|
|
533
|
+
*/
|
|
534
|
+
function getHlsCodec(type, codecs) {
|
|
535
|
+
if (type === "audio") return "mp4a.40.2";
|
|
536
|
+
else if (type === "video") return codecs?.split(",").at(0) ?? "";
|
|
537
|
+
else return "";
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
//#endregion
|
|
541
|
+
//#region src/utils/dash/iso8601DurationToNumber.ts
|
|
542
|
+
/**
|
|
543
|
+
* @internal
|
|
544
|
+
*/
|
|
545
|
+
function iso8601DurationToNumber(isoDuration) {
|
|
546
|
+
const hours = /(?:([.,\d]+)H)/.exec(isoDuration);
|
|
547
|
+
const minutes = /(?:([.,\d]+)M)/.exec(isoDuration);
|
|
548
|
+
const seconds = /(?:([.,\d]+)S)/.exec(isoDuration);
|
|
549
|
+
let duration = 0;
|
|
550
|
+
if (hours) duration += +hours[1] * 60 * 60;
|
|
551
|
+
if (minutes) duration += +minutes[1] * 60;
|
|
552
|
+
if (seconds) duration += +seconds[1];
|
|
553
|
+
return duration;
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
//#endregion
|
|
557
|
+
//#region src/mapper/dash/mapDashToHam/utils/getInitializationUrl.ts
|
|
558
|
+
/**
|
|
559
|
+
* @internal
|
|
560
|
+
*
|
|
561
|
+
* Get the initialization url. It can be present on AdaptationSet or Representation.
|
|
562
|
+
*
|
|
563
|
+
* Url initialization is present on segments.
|
|
564
|
+
*
|
|
565
|
+
* @param adaptationSet - AdaptationSet to try to get the initialization url from
|
|
566
|
+
* @param representation - Representation to try to get the initialization url from
|
|
567
|
+
*/
|
|
568
|
+
function getInitializationUrl(adaptationSet, representation) {
|
|
569
|
+
let initializationUrl;
|
|
570
|
+
if (representation.SegmentBase) initializationUrl = representation.BaseURL[0] ?? "";
|
|
571
|
+
else if (adaptationSet.SegmentList || representation.SegmentList) initializationUrl = representation.SegmentList?.at(0)?.Initialization[0].$.sourceURL || adaptationSet.SegmentList?.at(0)?.Initialization[0].$.sourceURL;
|
|
572
|
+
if (adaptationSet.SegmentTemplate || representation.SegmentTemplate) {
|
|
573
|
+
initializationUrl = adaptationSet.SegmentTemplate?.at(0)?.$.initialization || representation.SegmentTemplate?.at(0)?.$.initialization;
|
|
574
|
+
if (initializationUrl?.includes("$RepresentationID$")) initializationUrl = initializationUrl.replace("$RepresentationID$", representation.$.id ?? "");
|
|
575
|
+
}
|
|
576
|
+
return initializationUrl;
|
|
577
|
+
}
|
|
578
|
+
|
|
579
|
+
//#endregion
|
|
580
|
+
//#region src/mapper/dash/mapDashToHam/mapTracks.ts
|
|
581
|
+
/**
|
|
582
|
+
* @internal
|
|
583
|
+
*
|
|
584
|
+
* Map dash components to ham tracks.
|
|
585
|
+
*
|
|
586
|
+
* @param adaptationSet - AdaptationSet of the dash manifest
|
|
587
|
+
* @param representation - Representation of the dash manifest
|
|
588
|
+
* @param segments - Segments from the representation of the dash manifest
|
|
589
|
+
* @param initializationUrl - Initialization url from the track
|
|
590
|
+
* @returns AudioTrack, VideoTrack or TextTrack depending on the type
|
|
591
|
+
*/
|
|
592
|
+
function mapTracks(adaptationSet, representation, segments, initializationUrl) {
|
|
593
|
+
if (!adaptationSet) throw new Error("Error: AdaptationSet is undefined");
|
|
594
|
+
const type = getContentType(adaptationSet, representation);
|
|
595
|
+
if (type === "video") return {
|
|
596
|
+
bandwidth: +(representation.$.bandwidth ?? 0),
|
|
597
|
+
codec: getCodec(adaptationSet, representation),
|
|
598
|
+
duration: getTrackDuration(segments),
|
|
599
|
+
frameRate: getFrameRate(adaptationSet, representation),
|
|
600
|
+
height: +(representation.$.height ?? 0),
|
|
601
|
+
id: representation.$.id ?? "",
|
|
602
|
+
language: getLanguage(adaptationSet),
|
|
603
|
+
par: adaptationSet.$.par ?? "",
|
|
604
|
+
sar: getSar(adaptationSet, representation),
|
|
605
|
+
scanType: representation.$.scanType ?? "",
|
|
606
|
+
segments,
|
|
607
|
+
type,
|
|
608
|
+
width: +(representation.$.width ?? 0),
|
|
609
|
+
urlInitialization: initializationUrl
|
|
610
|
+
};
|
|
611
|
+
else if (type === "audio") return {
|
|
612
|
+
bandwidth: +(representation.$.bandwidth ?? 0),
|
|
613
|
+
channels: getChannels(adaptationSet, representation),
|
|
614
|
+
codec: getCodec(adaptationSet, representation),
|
|
615
|
+
duration: getTrackDuration(segments),
|
|
616
|
+
id: representation.$.id ?? "",
|
|
617
|
+
language: getLanguage(adaptationSet),
|
|
618
|
+
sampleRate: getSampleRate(adaptationSet, representation),
|
|
619
|
+
segments,
|
|
620
|
+
type,
|
|
621
|
+
urlInitialization: initializationUrl
|
|
622
|
+
};
|
|
623
|
+
else return {
|
|
624
|
+
bandwidth: +(representation.$.bandwidth ?? 0),
|
|
625
|
+
codec: getCodec(adaptationSet, representation),
|
|
626
|
+
duration: getTrackDuration(segments),
|
|
627
|
+
id: representation.$.id ?? "",
|
|
628
|
+
language: getLanguage(adaptationSet),
|
|
629
|
+
segments,
|
|
630
|
+
type,
|
|
631
|
+
urlInitialization: initializationUrl
|
|
632
|
+
};
|
|
633
|
+
}
|
|
634
|
+
|
|
635
|
+
//#endregion
|
|
636
|
+
//#region src/mapper/dash/mapDashToHam/mapDashToHam.ts
|
|
637
|
+
/**
|
|
638
|
+
* @internal
|
|
639
|
+
*
|
|
640
|
+
* Main function to map dash to ham.
|
|
641
|
+
*
|
|
642
|
+
* @param dash - Dash manifest to map
|
|
643
|
+
* @returns List of presentations in ham
|
|
644
|
+
*/
|
|
645
|
+
function mapDashToHam(dash) {
|
|
646
|
+
return dash.MPD.Period.map((period) => {
|
|
647
|
+
const duration = iso8601DurationToNumber(period.$.duration);
|
|
648
|
+
const presentationId = getPresentationId(period, duration);
|
|
649
|
+
const selectionSetGroups = {};
|
|
650
|
+
period.AdaptationSet.map((adaptationSet) => {
|
|
651
|
+
const tracks = adaptationSet.Representation.map((representation) => {
|
|
652
|
+
return mapTracks(adaptationSet, representation, mapSegments(adaptationSet, representation, duration), getInitializationUrl(adaptationSet, representation));
|
|
653
|
+
});
|
|
654
|
+
const group = getGroup(adaptationSet);
|
|
655
|
+
if (!selectionSetGroups[group]) selectionSetGroups[group] = {
|
|
656
|
+
id: group,
|
|
657
|
+
switchingSets: []
|
|
658
|
+
};
|
|
659
|
+
selectionSetGroups[group].switchingSets.push({
|
|
660
|
+
id: adaptationSet.$.id ?? adaptationSet.ContentComponent?.at(0)?.$.id ?? group,
|
|
661
|
+
tracks
|
|
662
|
+
});
|
|
663
|
+
});
|
|
664
|
+
return {
|
|
665
|
+
id: presentationId,
|
|
666
|
+
selectionSets: Object.values(selectionSetGroups)
|
|
667
|
+
};
|
|
668
|
+
});
|
|
669
|
+
}
|
|
670
|
+
|
|
671
|
+
//#endregion
|
|
672
|
+
//#region src/mapper/dash/mapHamToDash/trackToSegmentBase.ts
|
|
673
|
+
function trackToSegmentBase(track) {
|
|
674
|
+
const segments = [];
|
|
675
|
+
if (track.segments.length > 0 && track.byteRange && track.segments[0].byteRange && track.segments[0].byteRange.includes("@")) {
|
|
676
|
+
let firstSegment = void 0;
|
|
677
|
+
const initByteRange = track.byteRange.includes("-") ? track.byteRange.split("-")[1] : track.byteRange.includes("@") ? track.byteRange.split("@")[0] : "";
|
|
678
|
+
const initRange = +initByteRange - 1;
|
|
679
|
+
firstSegment = {
|
|
680
|
+
$: { indexRange: `${initByteRange}-${+(track.segments[0].byteRange.includes("-") ? track.segments[0].byteRange.split("-")[1] : track.segments[0].byteRange.includes("@") ? track.segments[0].byteRange.split("@")[1] : "") - 1}` },
|
|
681
|
+
Initialization: [{ $: { range: `0-${initRange}` } }]
|
|
682
|
+
};
|
|
683
|
+
if (firstSegment && track.type === "audio") {
|
|
684
|
+
const audioTrack = track;
|
|
685
|
+
firstSegment.$.timescale = audioTrack.sampleRate.toString() ?? "";
|
|
686
|
+
}
|
|
687
|
+
if (firstSegment) segments.push(firstSegment);
|
|
688
|
+
} else track.segments.forEach((segment) => {
|
|
689
|
+
let newSegment;
|
|
690
|
+
if (segment.byteRange) {
|
|
691
|
+
const initRange = +segment.byteRange.split("-")[0] - 1;
|
|
692
|
+
newSegment = {
|
|
693
|
+
$: { indexRange: segment.byteRange },
|
|
694
|
+
Initialization: [{ $: { range: `0-${initRange}` } }]
|
|
695
|
+
};
|
|
696
|
+
}
|
|
697
|
+
if (newSegment && track.type === "audio") {
|
|
698
|
+
const audioTrack = track;
|
|
699
|
+
newSegment.$.timescale = audioTrack.sampleRate.toString() ?? "";
|
|
700
|
+
}
|
|
701
|
+
if (newSegment) segments.push(newSegment);
|
|
702
|
+
});
|
|
703
|
+
return segments;
|
|
704
|
+
}
|
|
705
|
+
|
|
706
|
+
//#endregion
|
|
707
|
+
//#region src/mapper/dash/mapHamToDash/trackToSegmentList.ts
|
|
708
|
+
function trackToSegmentList(track) {
|
|
709
|
+
const segmentList = [];
|
|
710
|
+
const segmentURLs = [];
|
|
711
|
+
track.segments.forEach((segment) => {
|
|
712
|
+
segmentURLs.push({ $: { media: segment.url } });
|
|
713
|
+
});
|
|
714
|
+
if (!track.segments.at(0)?.byteRange) {
|
|
715
|
+
const timescale = getTimescale(track);
|
|
716
|
+
segmentList.push({
|
|
717
|
+
$: {
|
|
718
|
+
duration: (track.duration * timescale / segmentURLs.length).toString(),
|
|
719
|
+
timescale: timescale.toString()
|
|
720
|
+
},
|
|
721
|
+
Initialization: [{ $: { sourceURL: track.urlInitialization } }],
|
|
722
|
+
SegmentURL: segmentURLs
|
|
723
|
+
});
|
|
724
|
+
}
|
|
725
|
+
return segmentList;
|
|
726
|
+
}
|
|
727
|
+
|
|
728
|
+
//#endregion
|
|
729
|
+
//#region src/mapper/dash/mapHamToDash/utils/getFrameRate.ts
|
|
730
|
+
/**
|
|
731
|
+
* @internal
|
|
732
|
+
*
|
|
733
|
+
* Get the framerate from a track.
|
|
734
|
+
*
|
|
735
|
+
* If frameRate numerator is not present, it uses 30 as default.
|
|
736
|
+
*
|
|
737
|
+
* @param track - to get the framerate from
|
|
738
|
+
* @returns frame rate as a string formatted as `numerator/denominator`
|
|
739
|
+
*/
|
|
740
|
+
function getFrameRate$1(track) {
|
|
741
|
+
let frameRate = void 0;
|
|
742
|
+
if (track?.type === "video") {
|
|
743
|
+
const videoTrack = track;
|
|
744
|
+
frameRate = `${videoTrack.frameRate.frameRateNumerator ?? FRAME_RATE_NUMERATOR_30}`;
|
|
745
|
+
frameRate = videoTrack.frameRate.frameRateDenominator !== ZERO ? `${frameRate}/${videoTrack.frameRate.frameRateDenominator}` : frameRate;
|
|
746
|
+
}
|
|
747
|
+
return frameRate;
|
|
748
|
+
}
|
|
749
|
+
|
|
750
|
+
//#endregion
|
|
751
|
+
//#region src/mapper/dash/mapHamToDash/tracksToRepresentation.ts
|
|
752
|
+
function tracksToRepresentation(tracks) {
|
|
753
|
+
return tracks.map((track) => {
|
|
754
|
+
const representation = {
|
|
755
|
+
$: {
|
|
756
|
+
id: track.id,
|
|
757
|
+
bandwidth: track.bandwidth.toString()
|
|
758
|
+
},
|
|
759
|
+
SegmentBase: trackToSegmentBase(track),
|
|
760
|
+
SegmentList: trackToSegmentList(track)
|
|
761
|
+
};
|
|
762
|
+
representation.$.mimeType = `${track.type}/mp4`;
|
|
763
|
+
if (track.type === "video") {
|
|
764
|
+
const videoTrack = track;
|
|
765
|
+
representation.$ = {
|
|
766
|
+
...representation.$,
|
|
767
|
+
frameRate: getFrameRate$1(track),
|
|
768
|
+
width: videoTrack.width.toString(),
|
|
769
|
+
height: videoTrack.height.toString(),
|
|
770
|
+
codecs: videoTrack.codec
|
|
771
|
+
};
|
|
772
|
+
if (videoTrack.scanType) representation.$.scanType = videoTrack.scanType;
|
|
773
|
+
}
|
|
774
|
+
if (track.type === "audio") {
|
|
775
|
+
const audioTrack = track;
|
|
776
|
+
representation.$ = {
|
|
777
|
+
...representation.$,
|
|
778
|
+
audioSamplingRate: audioTrack.sampleRate.toString(),
|
|
779
|
+
codecs: audioTrack.codec
|
|
780
|
+
};
|
|
781
|
+
representation.AudioChannelConfiguration = [{ $: {
|
|
782
|
+
schemeIdUri: "urn:mpeg:dash:23003:3:audio_channel_configuration:2011",
|
|
783
|
+
value: audioTrack.channels.toString() ?? ""
|
|
784
|
+
} }];
|
|
785
|
+
}
|
|
786
|
+
if (track.segments[0]?.byteRange) representation.BaseURL = [track.segments[0].url];
|
|
787
|
+
return representation;
|
|
788
|
+
});
|
|
789
|
+
}
|
|
790
|
+
|
|
791
|
+
//#endregion
|
|
792
|
+
//#region src/mapper/dash/mapHamToDash/selectionSetsToAdaptationSet.ts
|
|
793
|
+
function selectionSetsToAdaptationSet(selectionsSets) {
|
|
794
|
+
return selectionsSets.flatMap((selectionSet) => {
|
|
795
|
+
return selectionSet.switchingSets.map((switchingSet) => {
|
|
796
|
+
const track = switchingSet.tracks[0];
|
|
797
|
+
return {
|
|
798
|
+
$: {
|
|
799
|
+
id: switchingSet.id,
|
|
800
|
+
group: selectionSet.id,
|
|
801
|
+
contentType: track?.type,
|
|
802
|
+
mimeType: `${track?.type}/mp4`,
|
|
803
|
+
frameRate: getFrameRate$1(track),
|
|
804
|
+
lang: track?.language,
|
|
805
|
+
codecs: track?.codec
|
|
806
|
+
},
|
|
807
|
+
Representation: tracksToRepresentation(switchingSet.tracks)
|
|
808
|
+
};
|
|
809
|
+
});
|
|
810
|
+
});
|
|
811
|
+
}
|
|
812
|
+
|
|
813
|
+
//#endregion
|
|
814
|
+
//#region src/utils/dash/numberToIso8601Duration.ts
|
|
815
|
+
/**
|
|
816
|
+
* @internal
|
|
817
|
+
*/
|
|
818
|
+
function numberToIso8601Duration(duration) {
|
|
819
|
+
const hours = Math.floor(duration / 3600);
|
|
820
|
+
const minutes = Math.floor(duration % 3600 / 60);
|
|
821
|
+
const seconds = duration % 60;
|
|
822
|
+
if (hours > 0) return `PT${hours}H${minutes}M${seconds}S`;
|
|
823
|
+
else if (minutes > 0) return `PT${minutes}M${seconds}S`;
|
|
824
|
+
return `PT${seconds}S`;
|
|
825
|
+
}
|
|
826
|
+
|
|
827
|
+
//#endregion
|
|
828
|
+
//#region src/mapper/dash/mapHamToDash/presentationsToPeriods.ts
|
|
829
|
+
function presentationsToPeriods(presentations) {
|
|
830
|
+
return presentations.map((presentation) => {
|
|
831
|
+
return {
|
|
832
|
+
$: {
|
|
833
|
+
duration: numberToIso8601Duration(presentation.selectionSets[0].switchingSets[0].tracks[0].duration),
|
|
834
|
+
id: presentation.id,
|
|
835
|
+
start: "PT0S"
|
|
836
|
+
},
|
|
837
|
+
AdaptationSet: selectionSetsToAdaptationSet(presentation.selectionSets)
|
|
838
|
+
};
|
|
839
|
+
});
|
|
840
|
+
}
|
|
841
|
+
|
|
842
|
+
//#endregion
|
|
843
|
+
//#region src/utils/dash/serializeDashManifest.ts
|
|
844
|
+
let xmlSerializer;
|
|
845
|
+
/**
|
|
846
|
+
* @internal
|
|
847
|
+
*/
|
|
848
|
+
function setDashSerializer(serializer) {
|
|
849
|
+
xmlSerializer = serializer;
|
|
850
|
+
}
|
|
851
|
+
/**
|
|
852
|
+
* @internal
|
|
853
|
+
*/
|
|
854
|
+
function getDashSerializer() {
|
|
855
|
+
return xmlSerializer;
|
|
856
|
+
}
|
|
857
|
+
/**
|
|
858
|
+
* @internal
|
|
859
|
+
*/
|
|
860
|
+
function serializeDashManifest(json) {
|
|
861
|
+
return xmlSerializer(json);
|
|
862
|
+
}
|
|
863
|
+
|
|
864
|
+
//#endregion
|
|
865
|
+
//#region src/mapper/dash/mapHamToDash/mapHamToDash.ts
|
|
866
|
+
function mapHamToDash(hamManifests) {
|
|
867
|
+
const periods = presentationsToPeriods(hamManifests);
|
|
868
|
+
return serializeDashManifest({ MPD: {
|
|
869
|
+
$: {
|
|
870
|
+
mediaPresentationDuration: periods[0].$.duration,
|
|
871
|
+
type: "static"
|
|
872
|
+
},
|
|
873
|
+
Period: periods
|
|
874
|
+
} });
|
|
875
|
+
}
|
|
876
|
+
|
|
877
|
+
//#endregion
|
|
878
|
+
//#region src/utils/dash/parseDashManifest.ts
|
|
879
|
+
let dashParser;
|
|
880
|
+
/**
|
|
881
|
+
* @internal
|
|
882
|
+
*/
|
|
883
|
+
function setDashParser(parser) {
|
|
884
|
+
dashParser = parser;
|
|
885
|
+
}
|
|
886
|
+
/**
|
|
887
|
+
* @internal
|
|
888
|
+
*/
|
|
889
|
+
function getDashParser() {
|
|
890
|
+
return dashParser;
|
|
891
|
+
}
|
|
892
|
+
/**
|
|
893
|
+
* @internal
|
|
894
|
+
* Parse XML to Json
|
|
895
|
+
*
|
|
896
|
+
* @param raw - Raw string containing the xml from the Dash Manifest
|
|
897
|
+
* @returns json with the Dash Manifest structure
|
|
898
|
+
*/
|
|
899
|
+
function parseDashManifest(raw) {
|
|
900
|
+
return dashParser(raw);
|
|
901
|
+
}
|
|
902
|
+
|
|
903
|
+
//#endregion
|
|
904
|
+
//#region src/utils/manifest/addMetadataToDash.ts
|
|
905
|
+
function addMetadataToDash(dashManifest, manifest) {
|
|
906
|
+
if (!manifest.metadata) manifest.metadata = /* @__PURE__ */ new Map();
|
|
907
|
+
if (dashManifest.MPD.$ && dashManifest.MPD.$.profiles) manifest.metadata.set("profiles", dashManifest.MPD.$.profiles);
|
|
908
|
+
if (dashManifest.MPD.$ && dashManifest.MPD.$.type) manifest.metadata.set("type", dashManifest.MPD.$.type);
|
|
909
|
+
return manifest;
|
|
910
|
+
}
|
|
911
|
+
|
|
912
|
+
//#endregion
|
|
913
|
+
//#region src/utils/manifest/getMetadata.ts
|
|
914
|
+
function getMetadata(manifest) {
|
|
915
|
+
const metadata = manifest?.metadata;
|
|
916
|
+
return JSON.parse(JSON.stringify(metadata));
|
|
917
|
+
}
|
|
918
|
+
|
|
919
|
+
//#endregion
|
|
920
|
+
//#region src/mapper/dash/DashMapper.ts
|
|
921
|
+
var DashMapper = class {
|
|
922
|
+
getManifestMetadata() {
|
|
923
|
+
return getMetadata(this.manifest);
|
|
924
|
+
}
|
|
925
|
+
toHam(manifest) {
|
|
926
|
+
const dashManifest = parseDashManifest(manifest.manifest);
|
|
927
|
+
if (!dashManifest) return [];
|
|
928
|
+
addMetadataToDash(dashManifest, manifest);
|
|
929
|
+
return mapDashToHam(dashManifest);
|
|
930
|
+
}
|
|
931
|
+
toManifest(presentation) {
|
|
932
|
+
return {
|
|
933
|
+
manifest: mapHamToDash(presentation),
|
|
934
|
+
ancillaryManifests: [],
|
|
935
|
+
type: "dash"
|
|
936
|
+
};
|
|
937
|
+
}
|
|
938
|
+
};
|
|
939
|
+
|
|
940
|
+
//#endregion
|
|
941
|
+
//#region src/mapper/MapperContext.ts
|
|
942
|
+
var MapperContext = class MapperContext {
|
|
943
|
+
constructor() {}
|
|
944
|
+
static getInstance() {
|
|
945
|
+
if (!MapperContext.instance) MapperContext.instance = new MapperContext();
|
|
946
|
+
return MapperContext.instance;
|
|
947
|
+
}
|
|
948
|
+
setStrategy(strategy) {
|
|
949
|
+
this.strategy = strategy;
|
|
950
|
+
}
|
|
951
|
+
getHamFormat(manifest) {
|
|
952
|
+
return this.strategy.toHam(manifest);
|
|
953
|
+
}
|
|
954
|
+
getManifestFormat(presentation) {
|
|
955
|
+
return this.strategy.toManifest(presentation);
|
|
956
|
+
}
|
|
957
|
+
getManifestMetadata() {
|
|
958
|
+
return this.strategy.getManifestMetadata();
|
|
959
|
+
}
|
|
960
|
+
};
|
|
961
|
+
|
|
962
|
+
//#endregion
|
|
963
|
+
//#region src/services/converters/dashToHam.ts
|
|
964
|
+
/**
|
|
965
|
+
* Convert dash manifest into a ham object.
|
|
966
|
+
*
|
|
967
|
+
* @example
|
|
968
|
+
* Example on how to import the cmaf module and convert the dash `manifest`
|
|
969
|
+
* into the ham manifest.
|
|
970
|
+
* ```ts
|
|
971
|
+
* import cmaf from '@svta/common-media-library/cmaf-ham';
|
|
972
|
+
*
|
|
973
|
+
* const manifest = cmaf.dashToHam(dashManifest);
|
|
974
|
+
* ```
|
|
975
|
+
*
|
|
976
|
+
* @param manifest - String of the XML Dash manifest
|
|
977
|
+
* @returns List of presentations from ham
|
|
978
|
+
*
|
|
979
|
+
* @alpha
|
|
980
|
+
*/
|
|
981
|
+
function dashToHam(manifest) {
|
|
982
|
+
const mapperContext = MapperContext.getInstance();
|
|
983
|
+
mapperContext.setStrategy(new DashMapper());
|
|
984
|
+
return mapperContext.getHamFormat({
|
|
985
|
+
manifest,
|
|
986
|
+
type: "dash"
|
|
987
|
+
});
|
|
988
|
+
}
|
|
989
|
+
|
|
990
|
+
//#endregion
|
|
991
|
+
//#region src/services/converters/hamToDash.ts
|
|
992
|
+
/**
|
|
993
|
+
* Convert HAM object into Dash Manifest.
|
|
994
|
+
*
|
|
995
|
+
* @example
|
|
996
|
+
* Example on how to import the cmaf module and convert the ham `presentations`
|
|
997
|
+
* array into the dash manifest.
|
|
998
|
+
* ```ts
|
|
999
|
+
* import cmaf from '@svta/common-media-library/cmaf-ham';
|
|
1000
|
+
*
|
|
1001
|
+
* const manifest = cmaf.hamToDash(presentations);
|
|
1002
|
+
* ```
|
|
1003
|
+
*
|
|
1004
|
+
* @param presentation - List of presentations from ham
|
|
1005
|
+
* @returns Manifest object containing the Dash manifest as string
|
|
1006
|
+
*
|
|
1007
|
+
* @alpha
|
|
1008
|
+
*/
|
|
1009
|
+
function hamToDash(presentation) {
|
|
1010
|
+
const mapperContext = MapperContext.getInstance();
|
|
1011
|
+
mapperContext.setStrategy(new DashMapper());
|
|
1012
|
+
return mapperContext.getManifestFormat(presentation);
|
|
1013
|
+
}
|
|
1014
|
+
|
|
1015
|
+
//#endregion
|
|
1016
|
+
//#region src/mapper/hls/mapHamToHls/generateManifestPlaylistPiece.ts
|
|
1017
|
+
function generateManifestPlaylistPiece(track) {
|
|
1018
|
+
const mediaSequence = 0;
|
|
1019
|
+
const trackFileName = track.fileName ?? `${track.id}.m3u8`;
|
|
1020
|
+
let mainRef = "";
|
|
1021
|
+
let playlist = `#EXTM3U\n#EXT-X-TARGETDURATION:${track.duration / track.segments.length}\n#EXT-X-PLAYLIST-TYPE:VOD\n#EXT-X-MEDIA-SEQUENCE:${mediaSequence}\n`;
|
|
1022
|
+
if (track.type.toLowerCase() === "video") {
|
|
1023
|
+
const videoTrack = track;
|
|
1024
|
+
mainRef += `#EXT-X-STREAM-INF:BANDWIDTH=${videoTrack.bandwidth},CODECS="${videoTrack.codec}",RESOLUTION=${videoTrack.width}x${videoTrack.height}\n${trackFileName}\n`;
|
|
1025
|
+
playlist += getPlaylistData(videoTrack);
|
|
1026
|
+
} else if (track.type.toLowerCase() === "audio") {
|
|
1027
|
+
const audioTrack = track;
|
|
1028
|
+
mainRef += `#EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID="${audioTrack.id}",LANGUAGE="${audioTrack.language}",NAME="${audioTrack.id}",URI="${trackFileName}"\n`;
|
|
1029
|
+
playlist += getPlaylistData(audioTrack);
|
|
1030
|
+
} else if (track.type.toLowerCase() === "text") {
|
|
1031
|
+
const textTrack = track;
|
|
1032
|
+
mainRef += `#EXT-X-MEDIA:TYPE=SUBTITLES,GROUP-ID="${textTrack.id}",NAME="${textTrack.id}",LANGUAGE="${textTrack.language}",URI="${trackFileName}"\n`;
|
|
1033
|
+
}
|
|
1034
|
+
playlist += `${getSegments(track.segments)}#EXT-X-ENDLIST`;
|
|
1035
|
+
return {
|
|
1036
|
+
mainRef,
|
|
1037
|
+
playlist
|
|
1038
|
+
};
|
|
1039
|
+
}
|
|
1040
|
+
|
|
1041
|
+
//#endregion
|
|
1042
|
+
//#region src/mapper/hls/mapHamToHls/mapHamToHls.ts
|
|
1043
|
+
function mapHamToHls(presentations) {
|
|
1044
|
+
let mainManifest = `#EXTM3U\n#EXT-X-VERSION:7\n\n`;
|
|
1045
|
+
const playlists = [];
|
|
1046
|
+
presentations.map((presentation) => {
|
|
1047
|
+
presentation.selectionSets.map((selectionSet) => {
|
|
1048
|
+
selectionSet.switchingSets.map((switchingSet) => {
|
|
1049
|
+
switchingSet.tracks.map((track) => {
|
|
1050
|
+
const { mainRef, playlist } = generateManifestPlaylistPiece(track);
|
|
1051
|
+
mainManifest += mainRef;
|
|
1052
|
+
const manifestFileName = track.fileName ?? `${track.id}.m3u8`;
|
|
1053
|
+
playlists.push({
|
|
1054
|
+
manifest: playlist,
|
|
1055
|
+
type: "hls",
|
|
1056
|
+
fileName: manifestFileName
|
|
1057
|
+
});
|
|
1058
|
+
});
|
|
1059
|
+
});
|
|
1060
|
+
});
|
|
1061
|
+
});
|
|
1062
|
+
return {
|
|
1063
|
+
manifest: mainManifest,
|
|
1064
|
+
ancillaryManifests: playlists,
|
|
1065
|
+
type: "hls"
|
|
1066
|
+
};
|
|
1067
|
+
}
|
|
1068
|
+
|
|
1069
|
+
//#endregion
|
|
1070
|
+
//#region src/utils/hls/parseHlsManifest.ts
|
|
1071
|
+
let hlsParser;
|
|
1072
|
+
/**
|
|
1073
|
+
* @internal
|
|
1074
|
+
*/
|
|
1075
|
+
function setHlsParser(parser) {
|
|
1076
|
+
hlsParser = parser;
|
|
1077
|
+
}
|
|
1078
|
+
/**
|
|
1079
|
+
* @internal
|
|
1080
|
+
*/
|
|
1081
|
+
function getHlsParser() {
|
|
1082
|
+
return hlsParser;
|
|
1083
|
+
}
|
|
1084
|
+
/**
|
|
1085
|
+
* @internal
|
|
1086
|
+
*/
|
|
1087
|
+
function parseHlsManifest(text) {
|
|
1088
|
+
if (!text) {
|
|
1089
|
+
console.error("Can't parse empty HLS Manifest");
|
|
1090
|
+
return {};
|
|
1091
|
+
}
|
|
1092
|
+
return hlsParser(text);
|
|
1093
|
+
}
|
|
1094
|
+
|
|
1095
|
+
//#endregion
|
|
1096
|
+
//#region src/mapper/hls/mapHlsToHam/audioGroupsToSwitchingSets.ts
|
|
1097
|
+
/**
|
|
1098
|
+
* @internal
|
|
1099
|
+
*
|
|
1100
|
+
* This function is used to convert audio groups to switching sets.
|
|
1101
|
+
*
|
|
1102
|
+
*
|
|
1103
|
+
* @param mediaGroupsAudio - Any
|
|
1104
|
+
* @param manifestPlaylists - Array of Manifest
|
|
1105
|
+
* @returns Array of switchingSet
|
|
1106
|
+
*
|
|
1107
|
+
* @alpha
|
|
1108
|
+
*/
|
|
1109
|
+
function audioGroupsToSwitchingSets(mediaGroupsAudio, manifestPlaylists) {
|
|
1110
|
+
const audioSwitchingSets = [];
|
|
1111
|
+
const audioTracks = [];
|
|
1112
|
+
for (const audioEncodings in mediaGroupsAudio) {
|
|
1113
|
+
const encodings = mediaGroupsAudio[audioEncodings];
|
|
1114
|
+
for (const audio in encodings) {
|
|
1115
|
+
const { language, uri } = encodings[audio];
|
|
1116
|
+
const audioParsed = parseHlsManifest(manifestPlaylists.shift()?.manifest);
|
|
1117
|
+
const map = audioParsed?.segments[0]?.map;
|
|
1118
|
+
const segments = formatSegments(audioParsed?.segments);
|
|
1119
|
+
const byteRange = decodeByteRange(map?.byterange);
|
|
1120
|
+
audioTracks.push({
|
|
1121
|
+
id: audio,
|
|
1122
|
+
type: "audio",
|
|
1123
|
+
fileName: uri,
|
|
1124
|
+
codec: getHlsCodec("audio"),
|
|
1125
|
+
duration: getDuration(audioParsed, segments),
|
|
1126
|
+
language,
|
|
1127
|
+
bandwidth: 0,
|
|
1128
|
+
segments,
|
|
1129
|
+
sampleRate: 0,
|
|
1130
|
+
channels: 2,
|
|
1131
|
+
...byteRange && { byteRange },
|
|
1132
|
+
...map?.uri && { urlInitialization: map?.uri }
|
|
1133
|
+
});
|
|
1134
|
+
}
|
|
1135
|
+
}
|
|
1136
|
+
audioSwitchingSets.push({
|
|
1137
|
+
id: "audio",
|
|
1138
|
+
tracks: audioTracks
|
|
1139
|
+
});
|
|
1140
|
+
return audioSwitchingSets;
|
|
1141
|
+
}
|
|
1142
|
+
|
|
1143
|
+
//#endregion
|
|
1144
|
+
//#region src/mapper/hls/mapHlsToHam/subtitleGroupsToSwitchingSets.ts
|
|
1145
|
+
function subtitleGroupsToSwitchingSets(mediaGroupsSubtitles, manifestPlaylists) {
|
|
1146
|
+
const subtitleSwitchingSets = [];
|
|
1147
|
+
const textTracks = [];
|
|
1148
|
+
for (const subtitleEncodings in mediaGroupsSubtitles) {
|
|
1149
|
+
const encodings = mediaGroupsSubtitles[subtitleEncodings];
|
|
1150
|
+
for (const subtitle in encodings) {
|
|
1151
|
+
const { language, uri } = encodings[subtitle];
|
|
1152
|
+
const subtitleParsed = parseHlsManifest(manifestPlaylists.shift()?.manifest);
|
|
1153
|
+
const segments = formatSegments(subtitleParsed?.segments);
|
|
1154
|
+
textTracks.push({
|
|
1155
|
+
id: subtitle,
|
|
1156
|
+
type: "text",
|
|
1157
|
+
fileName: uri,
|
|
1158
|
+
codec: getHlsCodec("text"),
|
|
1159
|
+
duration: getDuration(subtitleParsed, segments),
|
|
1160
|
+
language,
|
|
1161
|
+
bandwidth: 0,
|
|
1162
|
+
segments
|
|
1163
|
+
});
|
|
1164
|
+
}
|
|
1165
|
+
}
|
|
1166
|
+
subtitleSwitchingSets.push({
|
|
1167
|
+
id: "text",
|
|
1168
|
+
tracks: textTracks
|
|
1169
|
+
});
|
|
1170
|
+
return subtitleSwitchingSets;
|
|
1171
|
+
}
|
|
1172
|
+
|
|
1173
|
+
//#endregion
|
|
1174
|
+
//#region src/mapper/hls/mapHlsToHam/videoPlaylistsToSwitchingSets.ts
|
|
1175
|
+
function videoPlaylistsToSwitchingSets(playlists, manifestPlaylists) {
|
|
1176
|
+
const switchingSetVideos = [];
|
|
1177
|
+
const videoTracks = [];
|
|
1178
|
+
let videoTrackId = 0;
|
|
1179
|
+
playlists.map((playlist) => {
|
|
1180
|
+
const parsedHlsManifest = parseHlsManifest(manifestPlaylists.shift()?.manifest);
|
|
1181
|
+
const segments = formatSegments(parsedHlsManifest?.segments);
|
|
1182
|
+
const { LANGUAGE, CODECS, BANDWIDTH } = playlist.attributes;
|
|
1183
|
+
const map = parsedHlsManifest?.segments?.at(0)?.map;
|
|
1184
|
+
const byteRange = decodeByteRange(map?.byterange);
|
|
1185
|
+
videoTracks.push({
|
|
1186
|
+
id: `video-${videoTrackId++}`,
|
|
1187
|
+
type: "video",
|
|
1188
|
+
fileName: playlist.uri,
|
|
1189
|
+
codec: getHlsCodec("video", CODECS),
|
|
1190
|
+
duration: getDuration(parsedHlsManifest, segments),
|
|
1191
|
+
language: LANGUAGE ?? "und",
|
|
1192
|
+
bandwidth: BANDWIDTH,
|
|
1193
|
+
segments,
|
|
1194
|
+
width: playlist.attributes.RESOLUTION.width,
|
|
1195
|
+
height: playlist.attributes.RESOLUTION.height,
|
|
1196
|
+
frameRate: {
|
|
1197
|
+
frameRateNumerator: playlist.attributes["FRAME-RATE"] ?? FRAME_RATE_NUMERATOR_30,
|
|
1198
|
+
frameRateDenominator: ZERO
|
|
1199
|
+
},
|
|
1200
|
+
par: "",
|
|
1201
|
+
sar: "",
|
|
1202
|
+
scanType: "",
|
|
1203
|
+
...byteRange && { byteRange },
|
|
1204
|
+
...map?.uri && { urlInitialization: map?.uri }
|
|
1205
|
+
});
|
|
1206
|
+
});
|
|
1207
|
+
switchingSetVideos.push({
|
|
1208
|
+
id: `video`,
|
|
1209
|
+
tracks: videoTracks
|
|
1210
|
+
});
|
|
1211
|
+
return switchingSetVideos;
|
|
1212
|
+
}
|
|
1213
|
+
|
|
1214
|
+
//#endregion
|
|
1215
|
+
//#region src/utils/manifest/addMetadataToHls.ts
|
|
1216
|
+
function addMetadataToHls(manifest, manifestParsed) {
|
|
1217
|
+
if (!manifest.metadata) manifest.metadata = /* @__PURE__ */ new Map();
|
|
1218
|
+
if (!manifestParsed.version) manifest.metadata.set("version", manifestParsed.version);
|
|
1219
|
+
if (!manifestParsed.mediaSequence) manifest.metadata.set("mediaSequence", manifestParsed.mediaSequence);
|
|
1220
|
+
return manifest;
|
|
1221
|
+
}
|
|
1222
|
+
|
|
1223
|
+
//#endregion
|
|
1224
|
+
//#region src/mapper/hls/mapHlsToHam/mapHlsToHam.ts
|
|
1225
|
+
function mapHlsToHam(manifest) {
|
|
1226
|
+
const mainManifestParsed = parseHlsManifest(manifest.manifest);
|
|
1227
|
+
const manifestHls = addMetadataToHls(manifest, mainManifestParsed);
|
|
1228
|
+
const selectionSets = [];
|
|
1229
|
+
const manifestPlaylists = manifestHls.ancillaryManifests ? [...manifestHls.ancillaryManifests] : [];
|
|
1230
|
+
const audioSwitchingSets = audioGroupsToSwitchingSets(mainManifestParsed.mediaGroups?.AUDIO, manifestPlaylists);
|
|
1231
|
+
const subtitleSwitchingSets = subtitleGroupsToSwitchingSets(mainManifestParsed.mediaGroups?.SUBTITLES, manifestPlaylists);
|
|
1232
|
+
const videoSwitchingSets = videoPlaylistsToSwitchingSets(mainManifestParsed.playlists, manifestPlaylists);
|
|
1233
|
+
let selectionSetId = 0;
|
|
1234
|
+
if (audioSwitchingSets.length > 0) selectionSets.push({
|
|
1235
|
+
id: (selectionSetId++).toString(),
|
|
1236
|
+
switchingSets: audioSwitchingSets
|
|
1237
|
+
});
|
|
1238
|
+
if (subtitleSwitchingSets.length > 0) selectionSets.push({
|
|
1239
|
+
id: (selectionSetId++).toString(),
|
|
1240
|
+
switchingSets: subtitleSwitchingSets
|
|
1241
|
+
});
|
|
1242
|
+
if (videoSwitchingSets.length > 0) selectionSets.push({
|
|
1243
|
+
id: (selectionSetId++).toString(),
|
|
1244
|
+
switchingSets: videoSwitchingSets
|
|
1245
|
+
});
|
|
1246
|
+
let presentationId = 0;
|
|
1247
|
+
return [{
|
|
1248
|
+
id: (presentationId++).toString(),
|
|
1249
|
+
selectionSets
|
|
1250
|
+
}];
|
|
1251
|
+
}
|
|
1252
|
+
|
|
1253
|
+
//#endregion
|
|
1254
|
+
//#region src/mapper/hls/HlsMapper.ts
|
|
1255
|
+
var HlsMapper = class {
|
|
1256
|
+
getManifestMetadata() {
|
|
1257
|
+
return getMetadata(this.manifest);
|
|
1258
|
+
}
|
|
1259
|
+
toHam(manifest) {
|
|
1260
|
+
const presentations = mapHlsToHam(manifest);
|
|
1261
|
+
this.manifest = manifest;
|
|
1262
|
+
return presentations;
|
|
1263
|
+
}
|
|
1264
|
+
toManifest(presentation) {
|
|
1265
|
+
return mapHamToHls(presentation);
|
|
1266
|
+
}
|
|
1267
|
+
};
|
|
1268
|
+
|
|
1269
|
+
//#endregion
|
|
1270
|
+
//#region src/services/converters/hamToHls.ts
|
|
1271
|
+
/**
|
|
1272
|
+
* Convert ham object into a hls manifest.
|
|
1273
|
+
*
|
|
1274
|
+
* @example
|
|
1275
|
+
* Example on how to import the cmaf module and convert the ham `presentations`
|
|
1276
|
+
* array into the hls manifest.
|
|
1277
|
+
* ```ts
|
|
1278
|
+
* import cmaf from '@svta/common-media-library/cmaf-ham';
|
|
1279
|
+
*
|
|
1280
|
+
* const manifest = cmaf.hamToHls(presentations);
|
|
1281
|
+
* ```
|
|
1282
|
+
*
|
|
1283
|
+
* @param presentation - List of presentations from ham
|
|
1284
|
+
* @returns Manifest object containing the Hls manifest as string and its playlists
|
|
1285
|
+
*
|
|
1286
|
+
* @alpha
|
|
1287
|
+
*/
|
|
1288
|
+
function hamToHls(presentation) {
|
|
1289
|
+
const mapperContext = MapperContext.getInstance();
|
|
1290
|
+
mapperContext.setStrategy(new HlsMapper());
|
|
1291
|
+
return mapperContext.getManifestFormat(presentation);
|
|
1292
|
+
}
|
|
1293
|
+
|
|
1294
|
+
//#endregion
|
|
1295
|
+
//#region src/services/converters/hlsToHam.ts
|
|
1296
|
+
/**
|
|
1297
|
+
* Convert hls manifest into a ham object.
|
|
1298
|
+
*
|
|
1299
|
+
* @example
|
|
1300
|
+
* Example on how to import the cmaf module and convert the hls `manifest` and
|
|
1301
|
+
* `ancillaryManifests` array into the ham manifest.
|
|
1302
|
+
* ```ts
|
|
1303
|
+
* import cmaf from '@svta/common-media-library/cmaf-ham';
|
|
1304
|
+
*
|
|
1305
|
+
* const manifest = cmaf.hlsToHam(hlsManifest);
|
|
1306
|
+
* ```
|
|
1307
|
+
*
|
|
1308
|
+
* @param manifest - String of the Main manifest
|
|
1309
|
+
* @param ancillaryManifests - Ancillary Manifests . Must be in order, first audio, subtitle and video
|
|
1310
|
+
* @returns List of presentations from ham
|
|
1311
|
+
*
|
|
1312
|
+
* @alpha
|
|
1313
|
+
*/
|
|
1314
|
+
function hlsToHam(manifest, ancillaryManifests) {
|
|
1315
|
+
const mapperContext = MapperContext.getInstance();
|
|
1316
|
+
mapperContext.setStrategy(new HlsMapper());
|
|
1317
|
+
return mapperContext.getHamFormat({
|
|
1318
|
+
manifest,
|
|
1319
|
+
ancillaryManifests: ancillaryManifests.map((ancillaryManifest) => ({
|
|
1320
|
+
manifest: ancillaryManifest,
|
|
1321
|
+
type: "hls"
|
|
1322
|
+
})),
|
|
1323
|
+
type: "hls"
|
|
1324
|
+
});
|
|
1325
|
+
}
|
|
1326
|
+
|
|
1327
|
+
//#endregion
|
|
1328
|
+
//#region src/services/getters/getTracksFromSwitchingSet.ts
|
|
1329
|
+
/**
|
|
1330
|
+
* Get a list of Tracks contained on a SwitchingSet
|
|
1331
|
+
*
|
|
1332
|
+
* @param switchingSet - SwitchingSet object from HAM
|
|
1333
|
+
* @param predicate - Filtering function
|
|
1334
|
+
* @returns Track[]
|
|
1335
|
+
*
|
|
1336
|
+
* @alpha
|
|
1337
|
+
*/
|
|
1338
|
+
function getTracksFromSwitchingSet(switchingSet, predicate) {
|
|
1339
|
+
const tracks = switchingSet.tracks;
|
|
1340
|
+
return predicate ? tracks.filter(predicate) : tracks;
|
|
1341
|
+
}
|
|
1342
|
+
|
|
1343
|
+
//#endregion
|
|
1344
|
+
//#region src/services/getters/getTracksFromSelectionSet.ts
|
|
1345
|
+
/**
|
|
1346
|
+
* Get a list of Tracks contained on a SelectionSet
|
|
1347
|
+
*
|
|
1348
|
+
* @param selectionSet - SelectionSet object from HAM
|
|
1349
|
+
* @param predicate - Filtering function
|
|
1350
|
+
* @returns Track[]
|
|
1351
|
+
*
|
|
1352
|
+
* @alpha
|
|
1353
|
+
*/
|
|
1354
|
+
function getTracksFromSelectionSet(selectionSet, predicate) {
|
|
1355
|
+
const tracks = selectionSet.switchingSets.flatMap((switchingSet) => getTracksFromSwitchingSet(switchingSet));
|
|
1356
|
+
return predicate ? tracks.filter(predicate) : tracks;
|
|
1357
|
+
}
|
|
1358
|
+
|
|
1359
|
+
//#endregion
|
|
1360
|
+
//#region src/services/getters/getTracksFromPresentation.ts
|
|
1361
|
+
/**
|
|
1362
|
+
* Get a list of Tracks contained on a Presentation
|
|
1363
|
+
*
|
|
1364
|
+
* @param presentation - Presentation object from HAM
|
|
1365
|
+
* @param predicate - Filtering function
|
|
1366
|
+
* @returns Track[]
|
|
1367
|
+
*
|
|
1368
|
+
* @alpha
|
|
1369
|
+
*/
|
|
1370
|
+
function getTracksFromPresentation(presentation, predicate) {
|
|
1371
|
+
const tracks = presentation.selectionSets.flatMap((selectionSet) => getTracksFromSelectionSet(selectionSet));
|
|
1372
|
+
return predicate ? tracks.filter(predicate) : tracks;
|
|
1373
|
+
}
|
|
1374
|
+
|
|
1375
|
+
//#endregion
|
|
1376
|
+
//#region src/services/validators/validateSegment.ts
|
|
1377
|
+
/**
|
|
1378
|
+
* Validate a segment.
|
|
1379
|
+
*
|
|
1380
|
+
* Validations:
|
|
1381
|
+
* - segment has duration
|
|
1382
|
+
* - segment has url
|
|
1383
|
+
*
|
|
1384
|
+
* @param segment - Segment from cmaf ham model
|
|
1385
|
+
* @param trackId - Optional: parent track id
|
|
1386
|
+
* @param prevValidation - Optional: validation object from parent previous validate method call
|
|
1387
|
+
* @returns Validation
|
|
1388
|
+
*
|
|
1389
|
+
* @alpha
|
|
1390
|
+
*/
|
|
1391
|
+
function validateSegment(segment, trackId, prevValidation) {
|
|
1392
|
+
const validation = prevValidation ?? {
|
|
1393
|
+
status: true,
|
|
1394
|
+
errorMessages: []
|
|
1395
|
+
};
|
|
1396
|
+
const moreInformation = trackId ? ` in the track with id = ${trackId}` : ".";
|
|
1397
|
+
if (!segment.duration) {
|
|
1398
|
+
validation.status = false;
|
|
1399
|
+
validation.errorMessages.push(`Segment duration is undefined${moreInformation}`);
|
|
1400
|
+
}
|
|
1401
|
+
if (!segment.url) {
|
|
1402
|
+
validation.status = false;
|
|
1403
|
+
validation.errorMessages.push(`Segment url is undefined${moreInformation}`);
|
|
1404
|
+
}
|
|
1405
|
+
return validation;
|
|
1406
|
+
}
|
|
1407
|
+
|
|
1408
|
+
//#endregion
|
|
1409
|
+
//#region src/services/validators/validateSegments.ts
|
|
1410
|
+
/**
|
|
1411
|
+
* Validate a list of segments.
|
|
1412
|
+
*
|
|
1413
|
+
* @example
|
|
1414
|
+
* ```ts
|
|
1415
|
+
* import cmaf, { Segment } from '@svta/common-media-library/cmaf-ham';
|
|
1416
|
+
* ...
|
|
1417
|
+
*
|
|
1418
|
+
* // const segments: Segment[] = ...;
|
|
1419
|
+
*
|
|
1420
|
+
* const validation = cmaf.validateSegments(segments);
|
|
1421
|
+
* ```
|
|
1422
|
+
*
|
|
1423
|
+
* Example output: `{ status: true|false, errorMessages: [...] }`
|
|
1424
|
+
*
|
|
1425
|
+
* @param segments - List of Segment from cmaf ham model
|
|
1426
|
+
* @param trackId - Optional: parent track id
|
|
1427
|
+
* @param prevValidation - Optional: validation object from parent previous validate method call
|
|
1428
|
+
* @returns Validation
|
|
1429
|
+
*
|
|
1430
|
+
* @alpha
|
|
1431
|
+
*
|
|
1432
|
+
*/
|
|
1433
|
+
function validateSegments(segments, trackId, prevValidation) {
|
|
1434
|
+
const validation = prevValidation ?? {
|
|
1435
|
+
status: true,
|
|
1436
|
+
errorMessages: []
|
|
1437
|
+
};
|
|
1438
|
+
segments.forEach((segment) => {
|
|
1439
|
+
validateSegment(segment, trackId, validation);
|
|
1440
|
+
});
|
|
1441
|
+
return validation;
|
|
1442
|
+
}
|
|
1443
|
+
|
|
1444
|
+
//#endregion
|
|
1445
|
+
//#region src/services/validators/validateTrack.ts
|
|
1446
|
+
/**
|
|
1447
|
+
* Validate a track.
|
|
1448
|
+
* It validates in cascade, calling each child validation method.
|
|
1449
|
+
*
|
|
1450
|
+
* Validations:
|
|
1451
|
+
* - track has id
|
|
1452
|
+
* - Invokes specific audio, video and text validations
|
|
1453
|
+
*
|
|
1454
|
+
* @example
|
|
1455
|
+
* ```ts
|
|
1456
|
+
* import cmaf, { Track } from '@svta/common-media-library/cmaf-ham';
|
|
1457
|
+
* ...
|
|
1458
|
+
*
|
|
1459
|
+
* // const track: Track = ...;
|
|
1460
|
+
*
|
|
1461
|
+
* const validation = cmaf.validateTrack(track);
|
|
1462
|
+
* ```
|
|
1463
|
+
*
|
|
1464
|
+
* Example output: `{ status: true|false, errorMessages: [...] }`
|
|
1465
|
+
*
|
|
1466
|
+
* @param track - Track from cmaf ham model
|
|
1467
|
+
* @param switchingSetId - Optional: parent switching set id
|
|
1468
|
+
* @param prevValidation - Optional: validation object from parent previous validate method call
|
|
1469
|
+
* @returns Validation
|
|
1470
|
+
*
|
|
1471
|
+
* @alpha
|
|
1472
|
+
*
|
|
1473
|
+
*/
|
|
1474
|
+
function validateTrack(track, switchingSetId, prevValidation) {
|
|
1475
|
+
const validation = prevValidation ?? {
|
|
1476
|
+
status: true,
|
|
1477
|
+
errorMessages: []
|
|
1478
|
+
};
|
|
1479
|
+
const moreInformation = switchingSetId ? ` in the switching set with id = ${switchingSetId}` : ".";
|
|
1480
|
+
if (!track.id) {
|
|
1481
|
+
validation.status = false;
|
|
1482
|
+
validation.errorMessages.push(`Track id is undefined${moreInformation}`);
|
|
1483
|
+
}
|
|
1484
|
+
switch (track.type) {
|
|
1485
|
+
case "video":
|
|
1486
|
+
_validateVideoTrack(track, switchingSetId, validation);
|
|
1487
|
+
break;
|
|
1488
|
+
case "audio":
|
|
1489
|
+
_validateAudioTrack(track, switchingSetId, validation);
|
|
1490
|
+
break;
|
|
1491
|
+
case "text":
|
|
1492
|
+
_validateTextTrack(track, switchingSetId, validation);
|
|
1493
|
+
break;
|
|
1494
|
+
}
|
|
1495
|
+
validateSegments(track.segments, track.id, validation);
|
|
1496
|
+
return validation;
|
|
1497
|
+
}
|
|
1498
|
+
/**
|
|
1499
|
+
* @internal
|
|
1500
|
+
*
|
|
1501
|
+
* Validate video Track
|
|
1502
|
+
*
|
|
1503
|
+
* Validations:
|
|
1504
|
+
* - track has codec
|
|
1505
|
+
*
|
|
1506
|
+
* @param videoTrack - Video track to validate
|
|
1507
|
+
* @param switchingSetId - Optional: id from the switching set containing the track (Only used for logs)
|
|
1508
|
+
* @param prevValidation - Optional: validation object from parent previous validate method call
|
|
1509
|
+
* @returns Validation object
|
|
1510
|
+
* @see Validation
|
|
1511
|
+
*/
|
|
1512
|
+
function _validateVideoTrack(videoTrack, switchingSetId, prevValidation) {
|
|
1513
|
+
const validation = prevValidation ?? {
|
|
1514
|
+
status: true,
|
|
1515
|
+
errorMessages: []
|
|
1516
|
+
};
|
|
1517
|
+
const moreInformation = switchingSetId ? ` in the switching set with id = ${switchingSetId}` : ".";
|
|
1518
|
+
if (!videoTrack.codec) {
|
|
1519
|
+
validation.status = false;
|
|
1520
|
+
validation.errorMessages.push(`VideoTrack with id: ${videoTrack.id} does not have codec${moreInformation}`);
|
|
1521
|
+
}
|
|
1522
|
+
return validation;
|
|
1523
|
+
}
|
|
1524
|
+
/**
|
|
1525
|
+
* @internal
|
|
1526
|
+
*
|
|
1527
|
+
* Validate Audio Track
|
|
1528
|
+
*
|
|
1529
|
+
* Validations:
|
|
1530
|
+
* - track has codec
|
|
1531
|
+
*
|
|
1532
|
+
* @param audioTrack - Audio track to validate
|
|
1533
|
+
* @param switchingSetId - Optional: id from the switching set containing the track (Only used for logs)
|
|
1534
|
+
* @param prevValidation - Optional: validation object from parent previous validate method call
|
|
1535
|
+
* @returns Validation object
|
|
1536
|
+
* @see Validation
|
|
1537
|
+
*/
|
|
1538
|
+
function _validateAudioTrack(audioTrack, switchingSetId, prevValidation) {
|
|
1539
|
+
const validation = prevValidation ?? {
|
|
1540
|
+
status: true,
|
|
1541
|
+
errorMessages: []
|
|
1542
|
+
};
|
|
1543
|
+
const moreInformation = switchingSetId ? ` in the switching set with id = ${switchingSetId}` : ".";
|
|
1544
|
+
if (!audioTrack.codec) {
|
|
1545
|
+
validation.status = false;
|
|
1546
|
+
validation.errorMessages.push(`AudioTrack with id: ${audioTrack.id} does not have codec${moreInformation}`);
|
|
1547
|
+
}
|
|
1548
|
+
return validation;
|
|
1549
|
+
}
|
|
1550
|
+
/**
|
|
1551
|
+
* @internal
|
|
1552
|
+
*
|
|
1553
|
+
* Validate Text Track
|
|
1554
|
+
*
|
|
1555
|
+
* Validations:
|
|
1556
|
+
* - track has language
|
|
1557
|
+
*
|
|
1558
|
+
* @param textTrack - Text track to validate
|
|
1559
|
+
* @param switchingSetId - Optional: id from the switching set containing the track (Only used for logs)
|
|
1560
|
+
* @param prevValidation - Optional: validation object from parent previous validate method call
|
|
1561
|
+
* @returns Validation object
|
|
1562
|
+
* @see Validation
|
|
1563
|
+
*/
|
|
1564
|
+
function _validateTextTrack(textTrack, switchingSetId, prevValidation) {
|
|
1565
|
+
const validation = prevValidation ?? {
|
|
1566
|
+
status: true,
|
|
1567
|
+
errorMessages: []
|
|
1568
|
+
};
|
|
1569
|
+
const moreInformation = switchingSetId ? ` in the switching set with id = ${switchingSetId}` : ".";
|
|
1570
|
+
if (!textTrack.language) {
|
|
1571
|
+
validation.status = false;
|
|
1572
|
+
validation.errorMessages.push(`TextTrack with id: ${textTrack.id} does not have codec${moreInformation}`);
|
|
1573
|
+
}
|
|
1574
|
+
return validation;
|
|
1575
|
+
}
|
|
1576
|
+
|
|
1577
|
+
//#endregion
|
|
1578
|
+
//#region src/services/validators/validateTracks.ts
|
|
1579
|
+
/**
|
|
1580
|
+
* Validate a list of tracks.
|
|
1581
|
+
* It validates in cascade, calling each child validation method.
|
|
1582
|
+
*
|
|
1583
|
+
* @example
|
|
1584
|
+
* ```ts
|
|
1585
|
+
* import cmaf, { Track } from '@svta/common-media-library/cmaf-ham';
|
|
1586
|
+
* ...
|
|
1587
|
+
*
|
|
1588
|
+
* // const tracks: Track[] = ...;
|
|
1589
|
+
*
|
|
1590
|
+
* const validation = cmaf.validateTracks(tracks);
|
|
1591
|
+
* ```
|
|
1592
|
+
*
|
|
1593
|
+
* Example output: `{ status: true|false, errorMessages: [...] }`
|
|
1594
|
+
*
|
|
1595
|
+
* @param tracks - List of Track from cmaf ham model
|
|
1596
|
+
* @param switchingSetId - Optional: parent switching set id
|
|
1597
|
+
* @param prevValidation - Optional: validation object from parent previous validate method call
|
|
1598
|
+
* @returns Validation
|
|
1599
|
+
*
|
|
1600
|
+
* @alpha
|
|
1601
|
+
*
|
|
1602
|
+
*/
|
|
1603
|
+
function validateTracks(tracks, switchingSetId, prevValidation) {
|
|
1604
|
+
const validation = prevValidation ?? {
|
|
1605
|
+
status: true,
|
|
1606
|
+
errorMessages: []
|
|
1607
|
+
};
|
|
1608
|
+
const moreInformation = switchingSetId ? ` in the switching set with id = ${switchingSetId}` : ".";
|
|
1609
|
+
let tracksDuration;
|
|
1610
|
+
tracks.forEach((track) => {
|
|
1611
|
+
if (!tracksDuration) tracksDuration = track.duration;
|
|
1612
|
+
if (tracksDuration !== track.duration) {
|
|
1613
|
+
validation.status = false;
|
|
1614
|
+
validation.errorMessages.push(`All the tracks must have the same duration${moreInformation}`);
|
|
1615
|
+
}
|
|
1616
|
+
validateTrack(track, switchingSetId, validation);
|
|
1617
|
+
});
|
|
1618
|
+
return validation;
|
|
1619
|
+
}
|
|
1620
|
+
|
|
1621
|
+
//#endregion
|
|
1622
|
+
//#region src/services/validators/validateSwitchingSet.ts
|
|
1623
|
+
/**
|
|
1624
|
+
* Validate a switching set.
|
|
1625
|
+
* It validates in cascade, calling each child validation method.
|
|
1626
|
+
*
|
|
1627
|
+
* Validations:
|
|
1628
|
+
* - SwitchingSet has id
|
|
1629
|
+
*
|
|
1630
|
+
* @example
|
|
1631
|
+
* ```ts
|
|
1632
|
+
* import cmaf, { SwitchingSet } from '@svta/common-media-library/cmaf-ham';
|
|
1633
|
+
* ...
|
|
1634
|
+
*
|
|
1635
|
+
* // const switchingSet: SwitchingSet = ...;
|
|
1636
|
+
*
|
|
1637
|
+
* const validation = cmaf.validateSwitchingSet(switchingSet);
|
|
1638
|
+
* ```
|
|
1639
|
+
*
|
|
1640
|
+
* Example output: `{ status: true|false, errorMessages: [...] }`
|
|
1641
|
+
*
|
|
1642
|
+
* @param switchingSet - SwitchingSet from cmaf ham model
|
|
1643
|
+
* @param selectionSetId - Optional: parent selection set id
|
|
1644
|
+
* @param prevValidation - Optional: validation object from parent previous validate method call
|
|
1645
|
+
* @returns Validation
|
|
1646
|
+
*
|
|
1647
|
+
* @alpha
|
|
1648
|
+
*
|
|
1649
|
+
*/
|
|
1650
|
+
function validateSwitchingSet(switchingSet, selectionSetId, prevValidation) {
|
|
1651
|
+
const validation = prevValidation ?? {
|
|
1652
|
+
status: true,
|
|
1653
|
+
errorMessages: []
|
|
1654
|
+
};
|
|
1655
|
+
const moreInformation = selectionSetId ? ` in the selection set with id = ${selectionSetId}` : ".";
|
|
1656
|
+
if (!switchingSet.id) {
|
|
1657
|
+
validation.status = false;
|
|
1658
|
+
validation.errorMessages.push(`SwitchingSet id is undefined${moreInformation}`);
|
|
1659
|
+
}
|
|
1660
|
+
validateTracks(switchingSet.tracks, switchingSet.id, validation);
|
|
1661
|
+
return validation;
|
|
1662
|
+
}
|
|
1663
|
+
|
|
1664
|
+
//#endregion
|
|
1665
|
+
//#region src/services/validators/validateSwitchingSets.ts
|
|
1666
|
+
/**
|
|
1667
|
+
* Validate a list of switching set.
|
|
1668
|
+
* It validates in cascade, calling each child validation method.
|
|
1669
|
+
*
|
|
1670
|
+
* @example
|
|
1671
|
+
* ```ts
|
|
1672
|
+
* import cmaf, { SwitchingSet } from '@svta/common-media-library/cmaf-ham';
|
|
1673
|
+
* ...
|
|
1674
|
+
*
|
|
1675
|
+
* // const switchingSets: SwitchingSet[] = ...;
|
|
1676
|
+
*
|
|
1677
|
+
* const validation = cmaf.validateSwitchingSets(switchingSets);
|
|
1678
|
+
* ```
|
|
1679
|
+
*
|
|
1680
|
+
* Example output: `{ status: true|false, errorMessages: [...] }`
|
|
1681
|
+
*
|
|
1682
|
+
* @param switchingSets - List of SwitchingSets from cmaf ham model
|
|
1683
|
+
* @param selectionSetId - Optional: parent selection set id
|
|
1684
|
+
* @param prevValidation - Optional: validation object from parent previous validate method call
|
|
1685
|
+
* @returns Validation
|
|
1686
|
+
*
|
|
1687
|
+
* @alpha
|
|
1688
|
+
*
|
|
1689
|
+
*/
|
|
1690
|
+
function validateSwitchingSets(switchingSets, selectionSetId, prevValidation) {
|
|
1691
|
+
const validation = prevValidation ?? {
|
|
1692
|
+
status: true,
|
|
1693
|
+
errorMessages: []
|
|
1694
|
+
};
|
|
1695
|
+
switchingSets.forEach((switchingSet) => {
|
|
1696
|
+
validateSwitchingSet(switchingSet, selectionSetId, validation);
|
|
1697
|
+
});
|
|
1698
|
+
return validation;
|
|
1699
|
+
}
|
|
1700
|
+
|
|
1701
|
+
//#endregion
|
|
1702
|
+
//#region src/services/validators/validateSelectionSet.ts
|
|
1703
|
+
/**
|
|
1704
|
+
* Validate a selection set.
|
|
1705
|
+
* It validates in cascade, calling each child validation method.
|
|
1706
|
+
*
|
|
1707
|
+
* Validations:
|
|
1708
|
+
* - SelectionSet has id
|
|
1709
|
+
*
|
|
1710
|
+
* @example
|
|
1711
|
+
* ```ts
|
|
1712
|
+
* import cmaf, { SelectionSet } from '@svta/common-media-library/cmaf-ham';
|
|
1713
|
+
* ...
|
|
1714
|
+
*
|
|
1715
|
+
* // const selectionSet: SelectionSet = ...;
|
|
1716
|
+
*
|
|
1717
|
+
* const validation = cmaf.validateSelectionSet(selectionSet);
|
|
1718
|
+
* ```
|
|
1719
|
+
*
|
|
1720
|
+
* Example output: `{ status: true|false, errorMessages: [...] }`
|
|
1721
|
+
*
|
|
1722
|
+
* @param selectionSet - SelectionSet from cmaf ham model
|
|
1723
|
+
* @param presentationId - Optional: parent presentation id
|
|
1724
|
+
* @param prevValidation - Optional: validation object from parent previous validate method call
|
|
1725
|
+
* @returns Validation
|
|
1726
|
+
*
|
|
1727
|
+
* @alpha
|
|
1728
|
+
*
|
|
1729
|
+
*/
|
|
1730
|
+
function validateSelectionSet(selectionSet, presentationId, prevValidation) {
|
|
1731
|
+
const validation = prevValidation ?? {
|
|
1732
|
+
status: true,
|
|
1733
|
+
errorMessages: []
|
|
1734
|
+
};
|
|
1735
|
+
const moreInformation = presentationId ? ` in the presentation with id = ${presentationId}` : ".";
|
|
1736
|
+
if (!selectionSet.id) {
|
|
1737
|
+
validation.status = false;
|
|
1738
|
+
validation.errorMessages.push(`SelectionSet id is undefined${moreInformation}`);
|
|
1739
|
+
}
|
|
1740
|
+
validateSwitchingSets(selectionSet.switchingSets, selectionSet.id, validation);
|
|
1741
|
+
return validation;
|
|
1742
|
+
}
|
|
1743
|
+
|
|
1744
|
+
//#endregion
|
|
1745
|
+
//#region src/services/validators/validateSelectionSets.ts
|
|
1746
|
+
/**
|
|
1747
|
+
* Validate a list of selection set.
|
|
1748
|
+
* It validates in cascade, calling each child validation method.
|
|
1749
|
+
*
|
|
1750
|
+
* @example
|
|
1751
|
+
* ```ts
|
|
1752
|
+
* import cmaf, { SelectionSet } from '@svta/common-media-library/cmaf-ham';
|
|
1753
|
+
* ...
|
|
1754
|
+
*
|
|
1755
|
+
* // const selectionSets: SelectionSet[] = ...;
|
|
1756
|
+
*
|
|
1757
|
+
* const validation = cmaf.validateSelectionSets(selectionSets);
|
|
1758
|
+
* ```
|
|
1759
|
+
*
|
|
1760
|
+
* Example output: `{ status: true|false, errorMessages: [...] }`
|
|
1761
|
+
*
|
|
1762
|
+
* @param selectionSets - List of SelectionSet from cmaf ham model
|
|
1763
|
+
* @param presentationId - Optional: parent presentation id
|
|
1764
|
+
* @param prevValidation - Optional: validation object from parent previous validate method call
|
|
1765
|
+
* @returns Validation
|
|
1766
|
+
*
|
|
1767
|
+
* @alpha
|
|
1768
|
+
*
|
|
1769
|
+
*/
|
|
1770
|
+
function validateSelectionSets(selectionSets, presentationId, prevValidation) {
|
|
1771
|
+
const validation = prevValidation ?? {
|
|
1772
|
+
status: true,
|
|
1773
|
+
errorMessages: []
|
|
1774
|
+
};
|
|
1775
|
+
selectionSets.forEach((selectionSet) => {
|
|
1776
|
+
validateSelectionSet(selectionSet, presentationId, validation);
|
|
1777
|
+
});
|
|
1778
|
+
return validation;
|
|
1779
|
+
}
|
|
1780
|
+
|
|
1781
|
+
//#endregion
|
|
1782
|
+
//#region src/services/validators/validatePresentation.ts
|
|
1783
|
+
/**
|
|
1784
|
+
* Validate a presentation.
|
|
1785
|
+
* It validates in cascade, calling each child validation method.
|
|
1786
|
+
*
|
|
1787
|
+
* Validations:
|
|
1788
|
+
* - Presentation has id
|
|
1789
|
+
*
|
|
1790
|
+
* @example
|
|
1791
|
+
* ```ts
|
|
1792
|
+
* import cmaf, { Presentation } from '@svta/common-media-library/cmaf-ham';
|
|
1793
|
+
* ...
|
|
1794
|
+
*
|
|
1795
|
+
* // const presentation: Presentation = ...;
|
|
1796
|
+
*
|
|
1797
|
+
* const validation = cmaf.validatePresentation(presentation);
|
|
1798
|
+
* ```
|
|
1799
|
+
*
|
|
1800
|
+
* Example output: `{ status: true|false, errorMessages: [...] }`
|
|
1801
|
+
*
|
|
1802
|
+
* @param presentation - Presentation from cmaf ham model
|
|
1803
|
+
* @returns Validation
|
|
1804
|
+
*
|
|
1805
|
+
* @alpha
|
|
1806
|
+
*
|
|
1807
|
+
*/
|
|
1808
|
+
function validatePresentation(presentation) {
|
|
1809
|
+
const validation = {
|
|
1810
|
+
status: true,
|
|
1811
|
+
errorMessages: []
|
|
1812
|
+
};
|
|
1813
|
+
if (!presentation.id) {
|
|
1814
|
+
validation.status = false;
|
|
1815
|
+
validation.errorMessages.push("Presentation id is undefined");
|
|
1816
|
+
}
|
|
1817
|
+
validateSelectionSets(presentation.selectionSets, presentation.id, validation);
|
|
1818
|
+
return validation;
|
|
1819
|
+
}
|
|
1820
|
+
|
|
1821
|
+
//#endregion
|
|
1822
|
+
export { calculateDuration, dashToHam, decodeByteRange, encodeByteRange, formatSegments, getChannels, getCodec, getContentType, getDashParser, getDashSerializer, getDuration, getFrameRate, getGroup, getHlsCodec, getHlsParser, getLanguage, getNumberOfSegments, getPlaylistData, getPresentationId, getSampleRate, getSar, getSegments, getTimescale, getTrackDuration, getTracksFromPresentation, getTracksFromSelectionSet, getTracksFromSwitchingSet, getUrlFromTemplate, getUrlInitialization, hamToDash, hamToHls, hlsToHam, iso8601DurationToNumber, mapSegmentBase, mapSegmentList, mapSegmentTemplate, mapSegments, numberToIso8601Duration, parseDashManifest, parseHlsManifest, serializeDashManifest, setDashParser, setDashSerializer, setHlsParser, validatePresentation, validateSegment, validateSegments, validateSelectionSet, validateSelectionSets, validateSwitchingSet, validateSwitchingSets, validateTrack, validateTracks };
|
|
20
1823
|
//# sourceMappingURL=index.js.map
|