1
0
Fork 0
mirror of https://github.com/Chocobozzz/PeerTube.git synced 2025-10-03 09:49:20 +02:00
Peertube/packages/tests/src/api/videos/generate-download.ts
2025-05-13 13:54:19 +02:00

180 lines
6.2 KiB
TypeScript

/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
import { getHLS } from '@peertube/peertube-core-utils'
import { HttpStatusCode, VideoDetails, VideoFile, VideoResolution } from '@peertube/peertube-models'
import { buildSUUID } from '@peertube/peertube-node-utils'
import {
ObjectStorageCommand,
PeerTubeServer,
cleanupTests,
createMultipleServers,
followAll,
setAccessTokensToServers,
setDefaultVideoChannel,
waitJobs
} from '@peertube/peertube-server-commands'
import { checkTmpIsEmpty } from '@tests/shared/directories.js'
import { probeResBody } from '@tests/shared/videos.js'
import { expect } from 'chai'
import { FfprobeData } from 'fluent-ffmpeg'
import { remove } from 'fs-extra'
import { basename } from 'path'
describe('Test generate download', function () {
const resolutions = [ VideoResolution.H_NOVIDEO, VideoResolution.H_144P ]
let servers: PeerTubeServer[]
before(async function () {
this.timeout(120000)
servers = await createMultipleServers(2)
await setAccessTokensToServers(servers)
await setDefaultVideoChannel(servers)
await followAll(servers)
})
function runSuite (serverGetter: () => PeerTubeServer, objectStorage?: ObjectStorageCommand) {
const seed = buildSUUID()
let server: PeerTubeServer
before(async function () {
this.timeout(120000)
server = serverGetter()
if (objectStorage) {
await objectStorage.prepareDefaultMockBuckets()
await server.kill()
await server.run(objectStorage.getDefaultMockConfig())
}
{
await server.config.enableTranscoding({ hls: true, webVideo: true, splitAudioAndVideo: false, resolutions })
await server.videos.quickUpload({ name: 'common-' + seed })
await waitJobs(servers)
}
{
await server.config.enableTranscoding({ webVideo: false, hls: true, splitAudioAndVideo: true, resolutions })
await server.videos.quickUpload({ name: 'splitted-' + seed })
await waitJobs(servers)
}
})
function getVideoFile (files: VideoFile[]) {
return files.find(f => f.hasVideo === true)
}
function getAudioFile (files: VideoFile[]) {
return files.find(f => f.hasAudio === true)
}
function getAudioOnlyFile (files: VideoFile[]) {
return files.find(f => f.hasAudio === true && f.hasVideo === false)
}
async function getProbe (name: 'common' | 'splitted', filesGetter: (video: VideoDetails) => number[]) {
const video = await servers[0].videos.findFull({ name: name + '-' + seed })
const body = await servers[0].videos.generateDownload({ videoId: video.id, videoFileIds: filesGetter(video) })
return probeResBody(body)
}
function checkProbe (probe: FfprobeData, options: { hasVideo: boolean, hasAudio: boolean, hasImage: boolean }) {
expect(probe.streams.some(s => s.codec_type === 'video' && s.codec_name !== 'mjpeg')).to.equal(options.hasVideo)
expect(probe.streams.some(s => s.codec_type === 'audio')).to.equal(options.hasAudio)
expect(probe.streams.some(s => s.codec_name === 'mjpeg')).to.equal(options.hasImage)
}
it('Should generate a classic web video file', async function () {
const probe = await getProbe('common', video => [ getVideoFile(video.files).id ])
checkProbe(probe, { hasAudio: true, hasVideo: true, hasImage: false })
})
it('Should generate a classic HLS file', async function () {
const probe = await getProbe('common', video => [ getVideoFile(getHLS(video).files).id ])
checkProbe(probe, { hasAudio: true, hasVideo: true, hasImage: false })
})
it('Should generate an audio only web video file', async function () {
const probe = await getProbe('common', video => [ getAudioOnlyFile(video.files).id ])
checkProbe(probe, { hasAudio: true, hasVideo: false, hasImage: true })
})
it('Should generate an audio only HLS file', async function () {
const probe = await getProbe('common', video => [ getAudioOnlyFile(getHLS(video).files).id ])
checkProbe(probe, { hasAudio: true, hasVideo: false, hasImage: true })
})
it('Should generate a video only file', async function () {
const probe = await getProbe('splitted', video => [ getVideoFile(getHLS(video).files).id ])
checkProbe(probe, { hasAudio: false, hasVideo: true, hasImage: false })
})
it('Should merge audio and video files', async function () {
const probe = await getProbe('splitted', video => [ getVideoFile(getHLS(video).files).id, getAudioFile(getHLS(video).files).id ])
checkProbe(probe, { hasAudio: true, hasVideo: true, hasImage: false })
})
it('Should have cleaned the TMP directory', async function () {
for (const server of servers) {
await checkTmpIsEmpty(server)
}
})
}
describe('Download crash', function () {
it('Should not crash the server on non existing file', async function () {
this.timeout(120000)
await servers[0].config.enableTranscoding({ webVideo: false, hls: true, splitAudioAndVideo: true, resolutions })
const { uuid } = await servers[0].videos.quickUpload({ name: 'crash' })
await waitJobs(servers)
for (const server of servers) {
const video = await server.videos.get({ id: uuid })
const file = getHLS(video).files.find(f => f.hasVideo)
await remove(servers[0].getDirectoryPath('streaming-playlists/hls/' + uuid + '/' + basename(file.fileUrl)))
await server.videos.generateDownload({
videoId: uuid,
videoFileIds: [ file.id ],
expectedStatus: server === servers[0]
? HttpStatusCode.OK_200
: HttpStatusCode.INTERNAL_SERVER_ERROR_500
})
}
})
})
for (const objectStorage of [ undefined, new ObjectStorageCommand() ]) {
const testName = objectStorage
? 'On Object Storage'
: 'On filesystem'
describe(testName, function () {
describe('Videos on local server', function () {
runSuite(() => servers[0], objectStorage)
})
describe('Videos on remote server', function () {
runSuite(() => servers[1], objectStorage)
})
})
}
after(async function () {
await cleanupTests(servers)
})
})