mirror of
https://github.com/Chocobozzz/PeerTube.git
synced 2025-10-05 10:49:28 +02:00
Fix transcoding of audio only videos
This commit is contained in:
parent
82246a0c8d
commit
6ef092f0da
7 changed files with 113 additions and 4 deletions
|
@ -66,7 +66,6 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<my-user-notifications
|
<my-user-notifications
|
||||||
#userNotifications
|
|
||||||
[ignoreLoadingBar]="true" [infiniteScroll]="false" [itemsPerPage]="10"
|
[ignoreLoadingBar]="true" [infiniteScroll]="false" [itemsPerPage]="10"
|
||||||
[markAllAsReadSubject]="markAllAsReadSubject" (notificationsLoaded)="onNotificationLoaded()"
|
[markAllAsReadSubject]="markAllAsReadSubject" (notificationsLoaded)="onNotificationLoaded()"
|
||||||
></my-user-notifications>
|
></my-user-notifications>
|
||||||
|
|
|
@ -5,6 +5,8 @@ import { AbstractCommand, OverrideCommandOptions } from '../shared/abstract-comm
|
||||||
|
|
||||||
export class ConfigCommand extends AbstractCommand {
|
export class ConfigCommand extends AbstractCommand {
|
||||||
|
|
||||||
|
private savedConfig: CustomConfig
|
||||||
|
|
||||||
static getConfigResolutions (enabled: boolean, with0p = false) {
|
static getConfigResolutions (enabled: boolean, with0p = false) {
|
||||||
return {
|
return {
|
||||||
'0p': enabled && with0p,
|
'0p': enabled && with0p,
|
||||||
|
@ -579,4 +581,14 @@ export class ConfigCommand extends AbstractCommand {
|
||||||
|
|
||||||
return this.updateCustomConfig({ ...options, newCustomConfig: merge({}, existing, options.newConfig) })
|
return this.updateCustomConfig({ ...options, newCustomConfig: merge({}, existing, options.newConfig) })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
async save () {
|
||||||
|
this.savedConfig = await this.getCustomConfig()
|
||||||
|
}
|
||||||
|
|
||||||
|
rollback () {
|
||||||
|
return this.updateCustomConfig({ newCustomConfig: this.savedConfig })
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
|
/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
|
||||||
|
|
||||||
import { HttpStatusCode, VideoDetails } from '@peertube/peertube-models'
|
import { HttpStatusCode, VideoDetails, VideoResolution } from '@peertube/peertube-models'
|
||||||
import { areMockObjectStorageTestsDisabled } from '@peertube/peertube-node-utils'
|
import { areMockObjectStorageTestsDisabled } from '@peertube/peertube-node-utils'
|
||||||
import {
|
import {
|
||||||
cleanupTests,
|
cleanupTests,
|
||||||
|
@ -253,6 +253,56 @@ function runTests (options: {
|
||||||
|
|
||||||
expect(video.publishedAt).to.equal(publishedAt)
|
expect(video.publishedAt).to.equal(publishedAt)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('Should transcode with an audio-only video', async function () {
|
||||||
|
this.timeout(60000)
|
||||||
|
|
||||||
|
await servers[0].config.enableTranscoding({
|
||||||
|
webVideo: true,
|
||||||
|
hls: false,
|
||||||
|
keepOriginal: false,
|
||||||
|
splitAudioAndVideo: false,
|
||||||
|
alwaysTranscodeOriginalResolution: false,
|
||||||
|
resolutions: [ VideoResolution.H_NOVIDEO ]
|
||||||
|
})
|
||||||
|
|
||||||
|
const { uuid } = await servers[0].videos.quickUpload({ name: 'quick' })
|
||||||
|
await waitJobs(servers)
|
||||||
|
|
||||||
|
// Only keep audio resolution
|
||||||
|
{
|
||||||
|
const video = await servers[0].videos.get({ id: uuid })
|
||||||
|
|
||||||
|
expect(video.streamingPlaylists).to.have.lengthOf(0)
|
||||||
|
|
||||||
|
for (const file of video.files) {
|
||||||
|
if (file.resolution.id !== VideoResolution.H_NOVIDEO) {
|
||||||
|
await servers[0].videos.removeWebVideoFile({ videoId: uuid, fileId: file.id })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
await servers[0].videos.runTranscoding({ videoId: uuid, transcodingType: 'hls' })
|
||||||
|
await waitJobs(servers)
|
||||||
|
|
||||||
|
await servers[0].videos.runTranscoding({ videoId: uuid, transcodingType: 'web-video' })
|
||||||
|
await waitJobs(servers)
|
||||||
|
await expectNoFailedTranscodingJob(servers[0])
|
||||||
|
|
||||||
|
for (const server of servers) {
|
||||||
|
const videoDetails = await server.videos.get({ id: uuid })
|
||||||
|
|
||||||
|
expect(videoDetails.files).to.have.lengthOf(1)
|
||||||
|
expect(videoDetails.streamingPlaylists).to.have.lengthOf(1)
|
||||||
|
expect(videoDetails.streamingPlaylists[0].files).to.have.lengthOf(1)
|
||||||
|
|
||||||
|
for (const files of videoDetails.files) {
|
||||||
|
expect(files.resolution.id).to.equal(VideoResolution.H_NOVIDEO)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (enableObjectStorage) await checkFilesInObjectStorage(objectStorage, videoDetails)
|
||||||
|
}
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('With split audio and video', function () {
|
describe('With split audio and video', function () {
|
||||||
|
|
|
@ -409,6 +409,32 @@ describe('Test video source management', function () {
|
||||||
await makeGetRequest({ url: server.url, path: video.thumbnailPath, expectedStatus: HttpStatusCode.OK_200 })
|
await makeGetRequest({ url: server.url, path: video.thumbnailPath, expectedStatus: HttpStatusCode.OK_200 })
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('Should replace the video with an audio only file', async function () {
|
||||||
|
await servers[0].config.save()
|
||||||
|
|
||||||
|
await servers[0].config.enableTranscoding({ webVideo: true, hls: true, resolutions: [ 480, 360, 240, 144 ] })
|
||||||
|
const { uuid } = await servers[0].videos.quickUpload({ name: 'future audio', fixture: 'video_short_360p.mp4' })
|
||||||
|
await waitJobs(servers)
|
||||||
|
|
||||||
|
{
|
||||||
|
const video = await servers[0].videos.get({ id: uuid })
|
||||||
|
expect(getAllFiles(video)).to.have.lengthOf(6)
|
||||||
|
}
|
||||||
|
|
||||||
|
const fixture = 'sample.ogg'
|
||||||
|
await servers[0].videos.replaceSourceFile({ videoId: uuid, fixture })
|
||||||
|
await waitJobs(servers)
|
||||||
|
|
||||||
|
for (const server of servers) {
|
||||||
|
const video = await server.videos.get({ id: uuid })
|
||||||
|
|
||||||
|
const files = getAllFiles(video)
|
||||||
|
expect(files).to.have.lengthOf(8)
|
||||||
|
}
|
||||||
|
|
||||||
|
await servers[0].config.rollback()
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('Autoblacklist', function () {
|
describe('Autoblacklist', function () {
|
||||||
|
|
|
@ -75,6 +75,25 @@ describe('Test replace file using peertube-runner program', function () {
|
||||||
await checkSourceFile({ server, fsCount: 2, fixture, uuid })
|
await checkSourceFile({ server, fsCount: 2, fixture, uuid })
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('Should replace the video by an audio file', async function () {
|
||||||
|
{
|
||||||
|
await server.videos.removeAllWebVideoFiles({ videoId: uuid })
|
||||||
|
const video = await server.videos.get({ id: uuid })
|
||||||
|
expect(getAllFiles(video)).to.have.lengthOf(2)
|
||||||
|
}
|
||||||
|
|
||||||
|
const fixture = 'sample.ogg'
|
||||||
|
await server.videos.replaceSourceFile({ videoId: uuid, fixture })
|
||||||
|
await waitJobs(server, { runnerJobs: true })
|
||||||
|
|
||||||
|
const video = await server.videos.get({ id: uuid })
|
||||||
|
|
||||||
|
const files = getAllFiles(video)
|
||||||
|
expect(files).to.have.lengthOf(4)
|
||||||
|
|
||||||
|
await checkSourceFile({ server, fsCount: 2, fixture, uuid })
|
||||||
|
})
|
||||||
|
|
||||||
after(async function () {
|
after(async function () {
|
||||||
if (peertubeRunner) {
|
if (peertubeRunner) {
|
||||||
await peertubeRunner.unregisterPeerTubeInstance({ runnerName: 'runner' })
|
await peertubeRunner.unregisterPeerTubeInstance({ runnerName: 'runner' })
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import { VideoResolution } from '@peertube/peertube-models'
|
||||||
import { CONFIG } from '@server/initializers/config.js'
|
import { CONFIG } from '@server/initializers/config.js'
|
||||||
import { logger } from '../logger.js'
|
import { logger } from '../logger.js'
|
||||||
|
|
||||||
|
@ -9,6 +10,8 @@ export function computeOutputFPS (options: {
|
||||||
}) {
|
}) {
|
||||||
const { resolution, isOriginResolution, type } = options
|
const { resolution, isOriginResolution, type } = options
|
||||||
|
|
||||||
|
if (resolution === VideoResolution.H_NOVIDEO) return 0
|
||||||
|
|
||||||
const settings = type === 'vod'
|
const settings = type === 'vod'
|
||||||
? buildTranscodingFPSOptions(CONFIG.TRANSCODING.FPS.MAX)
|
? buildTranscodingFPSOptions(CONFIG.TRANSCODING.FPS.MAX)
|
||||||
: buildTranscodingFPSOptions(CONFIG.LIVE.TRANSCODING.FPS.MAX)
|
: buildTranscodingFPSOptions(CONFIG.LIVE.TRANSCODING.FPS.MAX)
|
||||||
|
|
|
@ -1796,11 +1796,11 @@ export class VideoModel extends SequelizeModel<VideoModel> {
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
getMaxFPS () {
|
getMaxFPS () {
|
||||||
return this.getMaxQualityFile(VideoFileStream.VIDEO).fps
|
return this.getMaxQualityFile(VideoFileStream.VIDEO)?.fps || 0
|
||||||
}
|
}
|
||||||
|
|
||||||
getMaxResolution () {
|
getMaxResolution () {
|
||||||
return this.getMaxQualityFile(VideoFileStream.VIDEO).resolution
|
return this.getMaxQualityFile(VideoFileStream.VIDEO)?.resolution || this.getMaxQualityFile(VideoFileStream.AUDIO)?.resolution
|
||||||
}
|
}
|
||||||
|
|
||||||
hasAudio () {
|
hasAudio () {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue