1
0
Fork 0
mirror of https://github.com/Chocobozzz/PeerTube.git synced 2025-10-04 02:09:37 +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:
Chocobozzz 2024-07-23 16:38:51 +02:00 committed by Chocobozzz
parent e77ba2dfbc
commit 816f346a60
186 changed files with 5748 additions and 2807 deletions

View file

@ -1,4 +1,4 @@
import { pick, promisify0 } from '@peertube/peertube-core-utils'
import { arrayify, pick, promisify0 } from '@peertube/peertube-core-utils'
import {
AvailableEncoders,
EncoderOptionsBuilder,
@ -8,6 +8,7 @@ import {
} from '@peertube/peertube-models'
import { MutexInterface } from 'async-mutex'
import ffmpeg, { FfmpegCommand } from 'fluent-ffmpeg'
import { Readable } from 'node:stream'
export interface FFmpegCommandWrapperOptions {
availableEncoders?: AvailableEncoders
@ -83,15 +84,19 @@ export class FFmpegCommandWrapper {
this.command = undefined
}
buildCommand (input: string, inputFileMutexReleaser?: MutexInterface.Releaser) {
buildCommand (inputs: (string | Readable)[] | string | Readable, inputFileMutexReleaser?: MutexInterface.Releaser) {
if (this.command) throw new Error('Command is already built')
// We set cwd explicitly because ffmpeg appears to create temporary files when trancoding which fails in read-only file systems
this.command = ffmpeg(input, {
this.command = ffmpeg({
niceness: this.niceness,
cwd: this.tmpDirectory
})
for (const input of arrayify(inputs)) {
this.command.input(input)
}
if (this.threads > 0) {
// If we don't set any threads ffmpeg will chose automatically
this.command.outputOption('-threads ' + this.threads)
@ -117,7 +122,10 @@ export class FFmpegCommandWrapper {
this.command.on('start', cmdline => { shellCommand = cmdline })
this.command.on('error', (err, stdout, stderr) => {
if (silent !== true) this.logger.error('Error in ffmpeg.', { stdout, stderr, shellCommand, ...this.lTags })
if (silent !== true) this.logger.error('Error in ffmpeg.', { err, stdout, stderr, shellCommand, ...this.lTags })
err.stdout = stdout
err.stderr = stderr
if (this.onError) this.onError(err)