Files
PeerTube/client/src/standalone/videos/shared/playlist-fetcher.ts
Chocobozzz 816f346a60 Separate HLS audio and video streams
Allows:
  * The HLS player to propose an "Audio only" resolution
  * The live to output an "Audio only" resolution
  * The live to ingest and output an "Audio only" stream

 This feature is under a config for VOD videos and is enabled by default for lives

 In the future we can imagine:
  * To propose multiple audio streams for a specific video
  * To ingest an audio only VOD and just output an audio only "video"
    (the player would play the audio file and PeerTube would not
    generate additional resolutions)

This commit introduce a new way to download videos:
 * Add "/download/videos/generate/:videoId" endpoint where PeerTube can
   mux an audio only and a video only file to a mp4 container
 * The download client modal introduces a new default panel where the
   user can choose resolutions it wants to download
2024-08-05 08:31:59 +02:00

75 lines
2.2 KiB
TypeScript

import { HttpStatusCode, ResultList, VideoPlaylistElement } from '@peertube/peertube-models'
import { logger } from '../../../root-helpers'
import { AuthHTTP } from './auth-http'
import { getBackendUrl } from './url'
export class PlaylistFetcher {
constructor (private readonly http: AuthHTTP) {
}
async loadPlaylist (playlistId: string) {
const playlistPromise = this.loadPlaylistInfo(playlistId)
const playlistElementsPromise = this.loadPlaylistElements(playlistId)
let playlistResponse: Response
let isResponseOk: boolean
try {
playlistResponse = await playlistPromise
isResponseOk = playlistResponse.status === HttpStatusCode.OK_200
} catch (err) {
logger.error(err)
isResponseOk = false
}
if (!isResponseOk) {
if (playlistResponse?.status === HttpStatusCode.NOT_FOUND_404) {
throw new Error('This playlist does not exist.')
}
throw new Error('We cannot fetch the playlist. Please try again later.')
}
return { playlistResponse, videosResponse: await playlistElementsPromise }
}
async loadAllPlaylistVideos (playlistId: string, baseResult: ResultList<VideoPlaylistElement>) {
let elements = baseResult.data
let total = baseResult.total
let i = 0
while (total > elements.length && i < 10) {
const result = await this.loadPlaylistElements(playlistId, elements.length)
const json = await result.json()
total = json.total
elements = elements.concat(json.data)
i++
}
if (i === 10) {
logger.error('Cannot fetch all playlists elements, there are too many!')
}
return elements
}
private loadPlaylistInfo (playlistId: string): Promise<Response> {
return this.http.fetch(this.getPlaylistUrl(playlistId), { optionalAuth: true })
}
private loadPlaylistElements (playlistId: string, start = 0): Promise<Response> {
const url = new URL(this.getPlaylistUrl(playlistId) + '/videos')
url.search = new URLSearchParams({ start: '' + start, count: '100' }).toString()
return this.http.fetch(url.toString(), { optionalAuth: true })
}
private getPlaylistUrl (id: string) {
return getBackendUrl() + '/api/v1/video-playlists/' + id
}
}