diff --git a/scripts/utils.ts b/scripts/utils.ts index 029b06bb76..27b76471af 100644 --- a/scripts/utils.ts +++ b/scripts/utils.ts @@ -99,8 +99,8 @@ export function truncate(string: string, limit: number = 100) { type StreamInfo = { resolution: { width: number; height: number } bandwidth: number - frameRate: number - codecs: string + frameRate?: number + codecs?: string } export async function getStreamInfo( @@ -162,6 +162,10 @@ export async function getStreamInfo( if (!data) return undefined + return parseStreamInfo(url, data) +} + +export function parseStreamInfo(url: string, data: string): StreamInfo | undefined { let info: StreamInfo | undefined if (url.includes('.m3u8')) { @@ -173,7 +177,7 @@ export async function getStreamInfo( if (playlist && playlist.isMasterPlaylist && playlist.variants.length) { const v = orderBy(playlist.variants, ['bandwidth'], ['desc'])[0] - if (v && v.resolution && v.frameRate && v.codecs) { + if (v && v.resolution) { info = { resolution: { width: v.resolution.width, height: v.resolution.height }, bandwidth: v.bandwidth, diff --git a/tests/utils.test.ts b/tests/utils.test.ts new file mode 100644 index 0000000000..beed94c25d --- /dev/null +++ b/tests/utils.test.ts @@ -0,0 +1,45 @@ +import { describe, it, expect } from 'vitest' +import { parseStreamInfo } from '../scripts/utils' + +const url = 'https://example.com/live/playlist.m3u8' + +describe('parseStreamInfo', () => { + it('reads the resolution of a master playlist without FRAME-RATE', () => { + const playlist = [ + '#EXTM3U', + '#EXT-X-STREAM-INF:BANDWIDTH=2128000,CODECS="avc1.4d401f,mp4a.40.2",RESOLUTION=1280x720', + 'chunklist_720p.m3u8', + '#EXT-X-STREAM-INF:BANDWIDTH=1064000,CODECS="avc1.4d401e,mp4a.40.2",RESOLUTION=854x480', + 'chunklist_480p.m3u8' + ].join('\n') + + expect(parseStreamInfo(url, playlist)).toEqual({ + resolution: { width: 1280, height: 720 }, + bandwidth: 2128000, + frameRate: undefined, + codecs: 'avc1.4d401f,mp4a.40.2' + }) + }) + + it('reads the resolution of a master playlist without CODECS', () => { + const playlist = [ + '#EXTM3U', + '#EXT-X-STREAM-INF:BANDWIDTH=1500000,RESOLUTION=1024x576,FRAME-RATE=25.000', + 'tracks-v1/mono.m3u8' + ].join('\n') + + expect(parseStreamInfo(url, playlist)?.resolution).toEqual({ width: 1024, height: 576 }) + }) + + it('returns nothing for a media playlist or a master playlist without RESOLUTION', () => { + const media = ['#EXTM3U', '#EXT-X-TARGETDURATION:6', '#EXTINF:6.0,', 'segment_1.ts'].join('\n') + const audioOnly = [ + '#EXTM3U', + '#EXT-X-STREAM-INF:BANDWIDTH=128000,CODECS="mp4a.40.2"', + 'audio.m3u8' + ].join('\n') + + expect(parseStreamInfo(url, media)).toBeUndefined() + expect(parseStreamInfo(url, audioOnly)).toBeUndefined() + }) +})