mirror of
https://github.com/Chocobozzz/PeerTube.git
synced 2025-10-04 10:19:35 +02:00
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
This commit is contained in:
parent
e77ba2dfbc
commit
816f346a60
186 changed files with 5748 additions and 2807 deletions
|
@ -1,17 +1,17 @@
|
|||
import { MutexInterface } from 'async-mutex'
|
||||
import { Job } from 'bullmq'
|
||||
import { ensureDir, move } from 'fs-extra/esm'
|
||||
import { join } from 'path'
|
||||
import { pick } from '@peertube/peertube-core-utils'
|
||||
import { getVideoStreamDuration, HLSFromTSTranscodeOptions, HLSTranscodeOptions } from '@peertube/peertube-ffmpeg'
|
||||
import { retryTransactionWrapper } from '@server/helpers/database-utils.js'
|
||||
import { createTorrentAndSetInfoHash } from '@server/helpers/webtorrent.js'
|
||||
import { sequelizeTypescript } from '@server/initializers/database.js'
|
||||
import { MVideo } from '@server/types/models/index.js'
|
||||
import { getVideoStreamDuration } from '@peertube/peertube-ffmpeg'
|
||||
import { MutexInterface } from 'async-mutex'
|
||||
import { Job } from 'bullmq'
|
||||
import { ensureDir, move } from 'fs-extra/esm'
|
||||
import { join } from 'path'
|
||||
import { CONFIG } from '../../initializers/config.js'
|
||||
import { VideoFileModel } from '../../models/video/video-file.js'
|
||||
import { VideoStreamingPlaylistModel } from '../../models/video/video-streaming-playlist.js'
|
||||
import { renameVideoFileInPlaylist, updatePlaylistAfterFileChange } from '../hls.js'
|
||||
import { renameVideoFileInPlaylist, updateM3U8AndShaPlaylist } from '../hls.js'
|
||||
import { generateHLSVideoFilename, getHlsResolutionPlaylistFilename } from '../paths.js'
|
||||
import { buildNewFile } from '../video-file.js'
|
||||
import { VideoPathManager } from '../video-path-manager.js'
|
||||
|
@ -28,7 +28,8 @@ export async function generateHlsPlaylistResolutionFromTS (options: {
|
|||
}) {
|
||||
return generateHlsPlaylistCommon({
|
||||
type: 'hls-from-ts' as 'hls-from-ts',
|
||||
inputPath: options.concatenatedTsFilePath,
|
||||
|
||||
videoInputPath: options.concatenatedTsFilePath,
|
||||
|
||||
...pick(options, [ 'video', 'resolution', 'fps', 'inputFileMutexReleaser', 'isAAC' ])
|
||||
})
|
||||
|
@ -37,18 +38,31 @@ export async function generateHlsPlaylistResolutionFromTS (options: {
|
|||
// Generate an HLS playlist from an input file, and update the master playlist
|
||||
export function generateHlsPlaylistResolution (options: {
|
||||
video: MVideo
|
||||
|
||||
videoInputPath: string
|
||||
separatedAudioInputPath: string
|
||||
|
||||
resolution: number
|
||||
fps: number
|
||||
copyCodecs: boolean
|
||||
inputFileMutexReleaser: MutexInterface.Releaser
|
||||
separatedAudio: boolean
|
||||
job?: Job
|
||||
}) {
|
||||
return generateHlsPlaylistCommon({
|
||||
type: 'hls' as 'hls',
|
||||
inputPath: options.videoInputPath,
|
||||
|
||||
...pick(options, [ 'video', 'resolution', 'fps', 'copyCodecs', 'inputFileMutexReleaser', 'job' ])
|
||||
...pick(options, [
|
||||
'videoInputPath',
|
||||
'separatedAudioInputPath',
|
||||
'video',
|
||||
'resolution',
|
||||
'fps',
|
||||
'copyCodecs',
|
||||
'separatedAudio',
|
||||
'inputFileMutexReleaser',
|
||||
'job'
|
||||
])
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -113,7 +127,7 @@ export async function onHLSVideoFileTranscoding (options: {
|
|||
|
||||
const savedVideoFile = await VideoFileModel.customUpsert(newVideoFile, 'streaming-playlist', undefined)
|
||||
|
||||
await updatePlaylistAfterFileChange(video, playlist)
|
||||
await updateM3U8AndShaPlaylist(video, playlist)
|
||||
|
||||
return { resolutionPlaylistPath, videoFile: savedVideoFile }
|
||||
} finally {
|
||||
|
@ -121,24 +135,43 @@ export async function onHLSVideoFileTranscoding (options: {
|
|||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Private
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
async function generateHlsPlaylistCommon (options: {
|
||||
type: 'hls' | 'hls-from-ts'
|
||||
video: MVideo
|
||||
inputPath: string
|
||||
|
||||
videoInputPath: string
|
||||
separatedAudioInputPath?: string
|
||||
|
||||
resolution: number
|
||||
fps: number
|
||||
|
||||
inputFileMutexReleaser: MutexInterface.Releaser
|
||||
|
||||
separatedAudio?: boolean
|
||||
|
||||
copyCodecs?: boolean
|
||||
isAAC?: boolean
|
||||
|
||||
job?: Job
|
||||
}) {
|
||||
const { type, video, inputPath, resolution, fps, copyCodecs, isAAC, job, inputFileMutexReleaser } = options
|
||||
const {
|
||||
type,
|
||||
video,
|
||||
videoInputPath,
|
||||
separatedAudioInputPath,
|
||||
resolution,
|
||||
fps,
|
||||
copyCodecs,
|
||||
separatedAudio,
|
||||
isAAC,
|
||||
job,
|
||||
inputFileMutexReleaser
|
||||
} = options
|
||||
|
||||
const transcodeDirectory = CONFIG.STORAGE.TMP_DIR
|
||||
|
||||
const videoTranscodedBasePath = join(transcodeDirectory, type)
|
||||
|
@ -150,15 +183,18 @@ async function generateHlsPlaylistCommon (options: {
|
|||
const resolutionPlaylistFilename = getHlsResolutionPlaylistFilename(videoFilename)
|
||||
const m3u8OutputPath = join(videoTranscodedBasePath, resolutionPlaylistFilename)
|
||||
|
||||
const transcodeOptions = {
|
||||
const transcodeOptions: HLSTranscodeOptions | HLSFromTSTranscodeOptions = {
|
||||
type,
|
||||
|
||||
inputPath,
|
||||
videoInputPath,
|
||||
separatedAudioInputPath,
|
||||
|
||||
outputPath: m3u8OutputPath,
|
||||
|
||||
resolution,
|
||||
fps,
|
||||
copyCodecs,
|
||||
separatedAudio,
|
||||
|
||||
isAAC,
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue