mirror of
https://github.com/Chocobozzz/PeerTube.git
synced 2026-09-03 20:53:09 -05:00
Add config to generate podcast audio file
This commit is contained in:
@@ -131,9 +131,7 @@ export class FFmpegVOD {
|
||||
const probe = await ffprobePromise(videoInputPath)
|
||||
const videoStreamInfo = await getVideoStreamDimensionsInfo(videoInputPath, probe)
|
||||
|
||||
scaleFilterValue = videoStreamInfo?.isPortraitMode === true
|
||||
? `w=${resolution}:h=-2`
|
||||
: `w=-2:h=${resolution}`
|
||||
scaleFilterValue = this.getScaleFilterValue({ resolution, portraitMode: videoStreamInfo?.isPortraitMode === true })
|
||||
}
|
||||
|
||||
await presetVOD({
|
||||
@@ -179,7 +177,7 @@ export class FFmpegVOD {
|
||||
canCopyVideo: true,
|
||||
videoStreamOnly: false,
|
||||
fps: options.fps,
|
||||
scaleFilterValue: this.getMergeAudioScaleFilterValue()
|
||||
scaleFilterValue: this.getScaleFilterValue({ resolution: options.resolution, portraitMode: false })
|
||||
})
|
||||
|
||||
command.outputOption('-preset:v veryfast')
|
||||
@@ -190,8 +188,15 @@ export class FFmpegVOD {
|
||||
}
|
||||
|
||||
// Avoid "height not divisible by 2" error
|
||||
private getMergeAudioScaleFilterValue () {
|
||||
return 'trunc(iw/2)*2:trunc(ih/2)*2'
|
||||
private getScaleFilterValue (options: {
|
||||
resolution: number
|
||||
portraitMode: boolean
|
||||
}) {
|
||||
const { resolution, portraitMode } = options
|
||||
|
||||
return portraitMode === true
|
||||
? `w=${resolution}:h=-2`
|
||||
: `w=-2:h=${resolution}`
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
@@ -169,6 +169,7 @@ export interface CustomConfig {
|
||||
resolutions: ConfigResolutions
|
||||
|
||||
alwaysTranscodeOriginalResolution: boolean
|
||||
alwaysTranscodePodcastOptimizedAudio: boolean
|
||||
|
||||
fps: {
|
||||
max: number
|
||||
|
||||
@@ -88,6 +88,7 @@ function checkInitialConfig (server: PeerTubeServer, data: CustomConfig) {
|
||||
expect(data.transcoding.alwaysTranscodeOriginalResolution).to.be.true
|
||||
expect(data.transcoding.fps.max).to.equal(60)
|
||||
expect(data.transcoding.webVideos.enabled).to.be.true
|
||||
expect(data.transcoding.alwaysTranscodePodcastOptimizedAudio).to.be.true
|
||||
expect(data.transcoding.hls.enabled).to.be.true
|
||||
expect(data.transcoding.hls.splitAudioAndVideo).to.be.false
|
||||
expect(data.transcoding.originalFile.keep).to.be.false
|
||||
@@ -295,6 +296,7 @@ function buildNewCustomConfig (server: PeerTubeServer): CustomConfig {
|
||||
'2160p': false
|
||||
},
|
||||
alwaysTranscodeOriginalResolution: false,
|
||||
alwaysTranscodePodcastOptimizedAudio: false,
|
||||
fps: {
|
||||
max: 120
|
||||
},
|
||||
|
||||
@@ -0,0 +1,117 @@
|
||||
/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
|
||||
|
||||
import {
|
||||
cleanupTests,
|
||||
ConfigCommand,
|
||||
createMultipleServers,
|
||||
doubleFollow,
|
||||
PeerTubeServer,
|
||||
setAccessTokensToServers,
|
||||
waitJobs
|
||||
} from '@peertube/peertube-server-commands'
|
||||
import { expect } from 'chai'
|
||||
|
||||
describe('Test force audio web video transcoding', function () {
|
||||
let servers: PeerTubeServer[] = []
|
||||
let videoId1: string
|
||||
let videoId2: string
|
||||
|
||||
before(async function () {
|
||||
servers = await createMultipleServers(2)
|
||||
|
||||
// Get the access tokens
|
||||
await setAccessTokensToServers(servers)
|
||||
|
||||
// Server 1 and server 2 follow each other
|
||||
await doubleFollow(servers[0], servers[1])
|
||||
|
||||
{
|
||||
const { uuid } = await servers[0].videos.quickUpload({ name: 'video 1' })
|
||||
videoId1 = uuid
|
||||
}
|
||||
|
||||
{
|
||||
const { uuid } = await servers[0].videos.quickUpload({ name: 'video 2' })
|
||||
videoId2 = uuid
|
||||
}
|
||||
|
||||
await servers[0].config.updateExistingConfig({
|
||||
newConfig: {
|
||||
transcoding: {
|
||||
enabled: true,
|
||||
originalFile: {
|
||||
keep: false
|
||||
},
|
||||
|
||||
allowAudioFiles: true,
|
||||
allowAdditionalExtensions: true,
|
||||
|
||||
resolutions: ConfigCommand.getCustomConfigResolutions([ 240, 720, 1080 ]),
|
||||
|
||||
alwaysTranscodeOriginalResolution: true,
|
||||
alwaysTranscodePodcastOptimizedAudio: true,
|
||||
|
||||
webVideos: {
|
||||
enabled: false
|
||||
},
|
||||
|
||||
hls: {
|
||||
enabled: true,
|
||||
splitAudioAndVideo: false
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
it('Should enable some web video resolutions and override global configuration for audio resolution', async function () {
|
||||
const { uuid } = await servers[0].videos.quickUpload({ name: 'video' })
|
||||
|
||||
await waitJobs(servers)
|
||||
|
||||
for (const server of servers) {
|
||||
const video = await server.videos.get({ id: uuid })
|
||||
|
||||
expect(video.files.map(f => f.resolution.id)).to.have.members([ 0 ])
|
||||
expect(video.streamingPlaylists[0].files.map(f => f.resolution.id)).to.have.members([ 240, 720 ])
|
||||
}
|
||||
})
|
||||
|
||||
it('Should force the audio resolution on manual web video transcoding', async function () {
|
||||
{
|
||||
const video = await servers[0].videos.get({ id: videoId1 })
|
||||
expect(video.files.map(f => f.resolution.id)).to.have.members([ 720 ])
|
||||
expect(video.streamingPlaylists).to.have.lengthOf(0)
|
||||
}
|
||||
|
||||
await servers[0].videos.runTranscoding({ transcodingType: 'web-video', videoId: videoId1 })
|
||||
await waitJobs(servers)
|
||||
|
||||
for (const server of servers) {
|
||||
const video = await server.videos.get({ id: videoId1 })
|
||||
expect(video.files.map(f => f.resolution.id)).to.have.members([ 0, 240, 720 ])
|
||||
expect(video.streamingPlaylists).to.have.lengthOf(0)
|
||||
}
|
||||
})
|
||||
|
||||
it('Should not force the audio resolution on manual hls transcoding', async function () {
|
||||
{
|
||||
const video = await servers[0].videos.get({ id: videoId2 })
|
||||
expect(video.files.map(f => f.resolution.id)).to.have.members([ 720 ])
|
||||
expect(video.streamingPlaylists).to.have.lengthOf(0)
|
||||
}
|
||||
|
||||
await servers[0].videos.runTranscoding({ transcodingType: 'hls', videoId: videoId2 })
|
||||
await waitJobs(servers)
|
||||
|
||||
for (const server of servers) {
|
||||
const video = await server.videos.get({ id: videoId2 })
|
||||
expect(video.files.map(f => f.resolution.id)).to.have.members([ 720 ])
|
||||
expect(video.streamingPlaylists[0].files.map(f => f.resolution.id)).to.have.members([ 240, 720 ])
|
||||
}
|
||||
})
|
||||
|
||||
after(async function () {
|
||||
await cleanupTests(servers)
|
||||
})
|
||||
})
|
||||
@@ -1,5 +1,6 @@
|
||||
export * from './audio-only.js'
|
||||
export * from './create-transcoding.js'
|
||||
export * from './force-audio-web-video-transcoding.js'
|
||||
export * from './hls.js'
|
||||
export * from './split-audio-and-video.js'
|
||||
export * from './transcoder-limits.js'
|
||||
|
||||
@@ -108,7 +108,16 @@ describe('Test syndication feeds', () => {
|
||||
await servers[0].comments.createThread({ videoId: id, text: 'comment on password protected video' })
|
||||
}
|
||||
|
||||
await serverHLSOnly.videos.upload({ attributes: { name: 'hls only video', nsfw: true } })
|
||||
{
|
||||
await serverHLSOnly.config.updateExistingConfig({
|
||||
newConfig: {
|
||||
transcoding: {
|
||||
alwaysTranscodePodcastOptimizedAudio: true
|
||||
}
|
||||
}
|
||||
})
|
||||
await serverHLSOnly.videos.upload({ attributes: { name: 'hls only video', nsfw: true } })
|
||||
}
|
||||
|
||||
await waitJobs([ ...servers, serverHLSOnly ])
|
||||
|
||||
@@ -201,7 +210,7 @@ describe('Test syndication feeds', () => {
|
||||
|
||||
const enclosure = xmlDoc.rss.channel.item.enclosure
|
||||
expect(enclosure).to.exist
|
||||
expectStartWith(enclosure['@_url'], `${serverHLSOnly.url}/download/videos/generate/`)
|
||||
expectStartWith(enclosure['@_url'], `${serverHLSOnly.url}/static/web-videos/`)
|
||||
expect(enclosure['@_url']).to.contain('.m4a')
|
||||
expect(enclosure['@_type']).to.equal('audio/x-m4a')
|
||||
|
||||
@@ -217,6 +226,11 @@ describe('Test syndication feeds', () => {
|
||||
expect(audioEnclosure['@_default']).to.equal(true)
|
||||
expect(audioEnclosure['podcast:source']['@_uri']).to.equal(enclosure['@_url'])
|
||||
|
||||
const videoEnclosure = alternateEnclosures.find(e => e['@_type'] === 'video/mp4')
|
||||
expect(videoEnclosure).to.exist
|
||||
expect(videoEnclosure['@_default']).to.equal(false)
|
||||
expectStartWith(videoEnclosure['podcast:source']['@_uri'], `${serverHLSOnly.url}/download/videos/generate/`)
|
||||
|
||||
const hlsEnclosure = alternateEnclosures.find(e => e['@_type'] === 'application/x-mpegURL')
|
||||
expect(hlsEnclosure).to.exist
|
||||
expect(hlsEnclosure['@_lang']).to.equal('zh')
|
||||
@@ -475,9 +489,9 @@ describe('Test syndication feeds', () => {
|
||||
const jsonObj = JSON.parse(json)
|
||||
expect(jsonObj.items.length).to.be.equal(1)
|
||||
expect(jsonObj.items[0].attachments).to.exist
|
||||
expect(jsonObj.items[0].attachments.length).to.be.eq(6)
|
||||
expect(jsonObj.items[0].attachments.length).to.be.eq(12)
|
||||
|
||||
for (let i = 0; i < 6; i++) {
|
||||
for (let i = 0; i < 12; i++) {
|
||||
expect(jsonObj.items[0].attachments[i].mime_type).to.be.eq('application/x-bittorrent')
|
||||
expect(jsonObj.items[0].attachments[i].size_in_bytes).to.be.greaterThan(0)
|
||||
expect(jsonObj.items[0].attachments[i].url).to.exist
|
||||
|
||||
@@ -86,6 +86,9 @@ describe('Test transcription in peertube-runner program', function () {
|
||||
})
|
||||
})
|
||||
|
||||
describe('With custom web video transcoding configuration', function () {
|
||||
|
||||
|
||||
describe('On object storage', function () {
|
||||
if (areMockObjectStorageTestsDisabled()) return
|
||||
|
||||
@@ -161,6 +164,7 @@ describe('Test transcription in peertube-runner program', function () {
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
describe('Check cleanup', function () {
|
||||
it('Should have an empty cache directory', async function () {
|
||||
await checkPeerTubeRunnerCacheIsEmpty(peertubeRunner, 'transcription')
|
||||
|
||||
@@ -4,6 +4,7 @@ import { VideoPrivacy, VideoResolution } from '@peertube/peertube-models'
|
||||
import { areMockObjectStorageTestsDisabled } from '@peertube/peertube-node-utils'
|
||||
import {
|
||||
cleanupTests,
|
||||
ConfigCommand,
|
||||
createMultipleServers,
|
||||
doubleFollow,
|
||||
ObjectStorageCommand,
|
||||
@@ -392,6 +393,45 @@ describe('Test VOD transcoding in peertube-runner program', function () {
|
||||
const resolutions = getAllFiles(video).map(f => f.resolution.id)
|
||||
expect(resolutions).to.have.members([ 240, 240, 480, 480 ])
|
||||
})
|
||||
|
||||
it('Should have a custom web video transcoding configuration', async function () {
|
||||
await servers[0].config.updateExistingConfig({
|
||||
newConfig: {
|
||||
transcoding: {
|
||||
enabled: true,
|
||||
originalFile: {
|
||||
keep: false
|
||||
},
|
||||
|
||||
allowAudioFiles: true,
|
||||
allowAdditionalExtensions: true,
|
||||
|
||||
resolutions: ConfigCommand.getCustomConfigResolutions([ 240, 720, 1080 ]),
|
||||
|
||||
alwaysTranscodeOriginalResolution: true,
|
||||
alwaysTranscodePodcastOptimizedAudio: true,
|
||||
|
||||
hls: {
|
||||
enabled: true,
|
||||
splitAudioAndVideo: false
|
||||
},
|
||||
|
||||
webVideos: {
|
||||
enabled: false
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
const { uuid } = await servers[0].videos.quickUpload({ name: 'video' })
|
||||
|
||||
await waitJobs(servers, { runnerJobs: true })
|
||||
|
||||
const video = await servers[0].videos.get({ id: uuid })
|
||||
|
||||
expect(video.files.map(f => f.resolution.id)).to.have.members([ 0 ])
|
||||
expect(video.streamingPlaylists[0].files.map(f => f.resolution.id)).to.have.members([ 240, 720 ])
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
Reference in New Issue
Block a user