diff --git a/packages/provider-utils/package.json b/packages/provider-utils/package.json index 4f0f106..b971795 100644 --- a/packages/provider-utils/package.json +++ b/packages/provider-utils/package.json @@ -18,6 +18,7 @@ "@movie-web/eslint-config": "workspace:^0.2.0", "@movie-web/prettier-config": "workspace:^0.1.0", "@movie-web/tsconfig": "workspace:^0.1.0", + "@types/hls-parser": "^0.8.7", "eslint": "^8.56.0", "prettier": "^3.1.1", "typescript": "^5.3.3" @@ -30,6 +31,7 @@ "prettier": "@movie-web/prettier-config", "dependencies": { "@movie-web/providers": "^2.2.0", + "hls-parser": "^0.10.8", "srt-webvtt": "^2.0.0", "tmdb-ts": "^1.6.1" } diff --git a/packages/provider-utils/src/video.ts b/packages/provider-utils/src/video.ts index 8fe74e3..50bbf92 100644 --- a/packages/provider-utils/src/video.ts +++ b/packages/provider-utils/src/video.ts @@ -1,3 +1,5 @@ +import { parse } from "hls-parser"; +import { MasterPlaylist } from "hls-parser/types"; import { default as toWebVTT } from "srt-webvtt"; import type { @@ -103,3 +105,28 @@ export function findHighestQuality( } return undefined; } + +export async function extractTracksFromHLS( + playlistUrl: string, + headers: Record, +) { + try { + const response = await fetch(playlistUrl, { headers }).then((res) => + res.text(), + ); + const playlist = parse(response); + if (!playlist.isMasterPlaylist) return null; + if (!(playlist instanceof MasterPlaylist)) return null; + + const tracks = playlist.variants.map((variant) => { + return { + video: variant.video, + audio: variant.audio, + subtitles: variant.subtitles, + }; + }); + return tracks; + } catch (e) { + return null; + } +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c50e331..8f66d45 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -182,6 +182,9 @@ importers: '@movie-web/providers': specifier: ^2.2.0 version: 2.2.0 + hls-parser: + specifier: ^0.10.8 + version: 0.10.8 srt-webvtt: specifier: ^2.0.0 version: 2.0.0 @@ -198,6 +201,9 @@ importers: '@movie-web/tsconfig': specifier: workspace:^0.1.0 version: link:../../tooling/typescript + '@types/hls-parser': + specifier: ^0.8.7 + version: 0.8.7 eslint: specifier: ^8.56.0 version: 8.56.0 @@ -3163,6 +3169,12 @@ packages: resolution: {integrity: sha512-qkcUlZmX6c4J8q45taBKTL3p+LbITgyx7qhlPYOdOHZB7B31K0mXbP5YA7i7SgDeEGuI9MnumiKPEMrxg8j3KQ==} dev: false + /@types/hls-parser@0.8.7: + resolution: {integrity: sha512-3ry9V6i/uhSbNdvBUENAqt2p5g+xKIbjkr5Qv4EaXe7eIJnaGQntFZalRLQlKoEop381a0LwUr2qNKKlxQC4TQ==} + dependencies: + '@types/node': 20.11.16 + dev: true + /@types/inquirer@6.5.0: resolution: {integrity: sha512-rjaYQ9b9y/VFGOpqBEXRavc3jh0a+e6evAbI31tMda8VlPaSy0AZJfXsvmIe3wklc7W6C3zCSfleuMXR7NOyXw==} dependencies: @@ -6338,6 +6350,10 @@ packages: source-map: 0.7.4 dev: false + /hls-parser@0.10.8: + resolution: {integrity: sha512-7FSqn7HYqXEW7I3qcgHJbtpNzi2nLKlBblPvHV6Uc6esVZ8JGfN3xUV7739gfaOh+w/O6TFxysLyW3GeLlAJTA==} + dev: false + /hmac-drbg@1.0.1: resolution: {integrity: sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg==} dependencies: