X-Git-Url: https://git.immae.eu/?a=blobdiff_plain;f=server%2Ftests%2Fapi%2Fvideos%2Fvideo-imports.ts;h=f082d4bd7d2446a994ac82c8bcebbb8ccdda9abd;hb=a3b472a12ec6e57dbe2f650419f8064864686eab;hp=4ef55c3af4bd44dfa12b26c5b6d62f5e078d709a;hpb=254d3579f5338f5fd775c17d15cdfc37078bcfb4;p=github%2FChocobozzz%2FPeerTube.git diff --git a/server/tests/api/videos/video-imports.ts b/server/tests/api/videos/video-imports.ts index 4ef55c3af..f082d4bd7 100644 --- a/server/tests/api/videos/video-imports.ts +++ b/server/tests/api/videos/video-imports.ts @@ -1,342 +1,618 @@ /* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */ import 'mocha' -import * as chai from 'chai' +import { expect } from 'chai' +import { pathExists, readdir, remove } from 'fs-extra' +import { join } from 'path' +import { FIXTURE_URLS, testCaptionFile, testImage } from '@server/tests/shared' +import { areHttpImportTestsDisabled } from '@shared/core-utils' +import { CustomConfig, HttpStatusCode, Video, VideoImportState, VideoPrivacy, VideoResolution, VideoState } from '@shared/models' import { - areHttpImportTestsDisabled, cleanupTests, - doubleFollow, createMultipleServers, - ImportsCommand, + createSingleServer, + doubleFollow, + getServerImportConfig, PeerTubeServer, setAccessTokensToServers, - testCaptionFile, - testImage, + setDefaultVideoChannel, waitJobs -} from '@shared/extra-utils' -import { VideoPrivacy, VideoResolution } from '@shared/models' +} from '@shared/server-commands' +import { DeepPartial } from '@shared/typescript-utils' + +async function checkVideosServer1 (server: PeerTubeServer, idHttp: string, idMagnet: string, idTorrent: string) { + const videoHttp = await server.videos.get({ id: idHttp }) + + expect(videoHttp.name).to.equal('small video - youtube') + // FIXME: youtube-dl seems broken + // expect(videoHttp.category.label).to.equal('News & Politics') + // expect(videoHttp.licence.label).to.equal('Attribution') + expect(videoHttp.language.label).to.equal('Unknown') + expect(videoHttp.nsfw).to.be.false + expect(videoHttp.description).to.equal('this is a super description') + expect(videoHttp.tags).to.deep.equal([ 'tag1', 'tag2' ]) + expect(videoHttp.files).to.have.lengthOf(1) + + const originallyPublishedAt = new Date(videoHttp.originallyPublishedAt) + expect(originallyPublishedAt.getDate()).to.equal(14) + expect(originallyPublishedAt.getMonth()).to.equal(0) + expect(originallyPublishedAt.getFullYear()).to.equal(2019) + + const videoMagnet = await server.videos.get({ id: idMagnet }) + const videoTorrent = await server.videos.get({ id: idTorrent }) + + for (const video of [ videoMagnet, videoTorrent ]) { + expect(video.category.label).to.equal('Misc') + expect(video.licence.label).to.equal('Unknown') + expect(video.language.label).to.equal('Unknown') + expect(video.nsfw).to.be.false + expect(video.description).to.equal('this is a super torrent description') + expect(video.tags).to.deep.equal([ 'tag_torrent1', 'tag_torrent2' ]) + expect(video.files).to.have.lengthOf(1) + } + + expect(videoTorrent.name).to.contain('你好 世界 720p.mp4') + expect(videoMagnet.name).to.contain('super peertube2 video') + + const bodyCaptions = await server.captions.list({ videoId: idHttp }) + expect(bodyCaptions.total).to.equal(2) +} + +async function checkVideoServer2 (server: PeerTubeServer, id: number | string) { + const video = await server.videos.get({ id }) -const expect = chai.expect + expect(video.name).to.equal('my super name') + expect(video.category.label).to.equal('Entertainment') + expect(video.licence.label).to.equal('Public Domain Dedication') + expect(video.language.label).to.equal('English') + expect(video.nsfw).to.be.false + expect(video.description).to.equal('my super description') + expect(video.tags).to.deep.equal([ 'supertag1', 'supertag2' ]) + + expect(video.files).to.have.lengthOf(1) + + const bodyCaptions = await server.captions.list({ videoId: id }) + expect(bodyCaptions.total).to.equal(2) +} describe('Test video imports', function () { - let servers: PeerTubeServer[] = [] - let channelIdServer1: number - let channelIdServer2: number if (areHttpImportTestsDisabled()) return - async function checkVideosServer1 (server: PeerTubeServer, idHttp: string, idMagnet: string, idTorrent: string) { - const videoHttp = await server.videos.get({ id: idHttp }) - - expect(videoHttp.name).to.equal('small video - youtube') - // FIXME: youtube-dl seems broken - // expect(videoHttp.category.label).to.equal('News & Politics') - // expect(videoHttp.licence.label).to.equal('Attribution') - expect(videoHttp.language.label).to.equal('Unknown') - expect(videoHttp.nsfw).to.be.false - expect(videoHttp.description).to.equal('this is a super description') - expect(videoHttp.tags).to.deep.equal([ 'tag1', 'tag2' ]) - expect(videoHttp.files).to.have.lengthOf(1) - - const originallyPublishedAt = new Date(videoHttp.originallyPublishedAt) - expect(originallyPublishedAt.getDate()).to.equal(14) - expect(originallyPublishedAt.getMonth()).to.equal(0) - expect(originallyPublishedAt.getFullYear()).to.equal(2019) - - const videoMagnet = await server.videos.get({ id: idMagnet }) - const videoTorrent = await server.videos.get({ id: idTorrent }) - - for (const video of [ videoMagnet, videoTorrent ]) { - expect(video.category.label).to.equal('Misc') - expect(video.licence.label).to.equal('Unknown') - expect(video.language.label).to.equal('Unknown') - expect(video.nsfw).to.be.false - expect(video.description).to.equal('this is a super torrent description') - expect(video.tags).to.deep.equal([ 'tag_torrent1', 'tag_torrent2' ]) - expect(video.files).to.have.lengthOf(1) - } + function runSuite (mode: 'youtube-dl' | 'yt-dlp') { - expect(videoTorrent.name).to.contain('你好 世界 720p.mp4') - expect(videoMagnet.name).to.contain('super peertube2 video') + describe('Import ' + mode, function () { + let servers: PeerTubeServer[] = [] - const bodyCaptions = await server.captions.listVideoCaptions({ videoId: idHttp }) - expect(bodyCaptions.total).to.equal(2) - } + before(async function () { + this.timeout(60_000) - async function checkVideoServer2 (server: PeerTubeServer, id: number | string) { - const video = await server.videos.get({ id }) + servers = await createMultipleServers(2, getServerImportConfig(mode)) - expect(video.name).to.equal('my super name') - expect(video.category.label).to.equal('Entertainment') - expect(video.licence.label).to.equal('Public Domain Dedication') - expect(video.language.label).to.equal('English') - expect(video.nsfw).to.be.false - expect(video.description).to.equal('my super description') - expect(video.tags).to.deep.equal([ 'supertag1', 'supertag2' ]) + await setAccessTokensToServers(servers) + await setDefaultVideoChannel(servers) - expect(video.files).to.have.lengthOf(1) + for (const server of servers) { + await server.config.updateExistingSubConfig({ + newConfig: { + transcoding: { + alwaysTranscodeOriginalResolution: false + } + } + }) + } - const bodyCaptions = await server.captions.listVideoCaptions({ videoId: id }) - expect(bodyCaptions.total).to.equal(2) - } + await doubleFollow(servers[0], servers[1]) + }) - before(async function () { - this.timeout(30_000) + it('Should import videos on server 1', async function () { + this.timeout(60_000) - // Run servers - servers = await createMultipleServers(2) + const baseAttributes = { + channelId: servers[0].store.channel.id, + privacy: VideoPrivacy.PUBLIC + } - await setAccessTokensToServers(servers) + { + const attributes = { ...baseAttributes, targetUrl: FIXTURE_URLS.youtube } + const { video } = await servers[0].imports.importVideo({ attributes }) + expect(video.name).to.equal('small video - youtube') - { - const { videoChannels } = await servers[0].users.getMyInfo() - channelIdServer1 = videoChannels[0].id - } + { + expect(video.thumbnailPath).to.match(new RegExp(`^/static/thumbnails/.+.jpg$`)) + expect(video.previewPath).to.match(new RegExp(`^/lazy-static/previews/.+.jpg$`)) - { - const { videoChannels } = await servers[1].users.getMyInfo() - channelIdServer2 = videoChannels[0].id - } + const suffix = mode === 'yt-dlp' + ? '_yt_dlp' + : '' - await doubleFollow(servers[0], servers[1]) - }) + await testImage(servers[0].url, 'video_import_thumbnail' + suffix, video.thumbnailPath) + await testImage(servers[0].url, 'video_import_preview' + suffix, video.previewPath) + } - it('Should import videos on server 1', async function () { - this.timeout(60_000) + const bodyCaptions = await servers[0].captions.list({ videoId: video.id }) + const videoCaptions = bodyCaptions.data + expect(videoCaptions).to.have.lengthOf(2) + + { + const enCaption = videoCaptions.find(caption => caption.language.id === 'en') + expect(enCaption).to.exist + expect(enCaption.language.label).to.equal('English') + expect(enCaption.captionPath).to.match(new RegExp(`^/lazy-static/video-captions/.+-en.vtt$`)) + + const regex = `WEBVTT[ \n]+Kind: captions[ \n]+` + + `(Language: en[ \n]+)?` + + `00:00:01.600 --> 00:00:04.200( position:\\d+% line:\\d+%)?[ \n]+English \\(US\\)[ \n]+` + + `00:00:05.900 --> 00:00:07.999( position:\\d+% line:\\d+%)?[ \n]+This is a subtitle in American English[ \n]+` + + `00:00:10.000 --> 00:00:14.000( position:\\d+% line:\\d+%)?[ \n]+Adding subtitles is very easy to do` + await testCaptionFile(servers[0].url, enCaption.captionPath, new RegExp(regex)) + } - const baseAttributes = { - channelId: channelIdServer1, - privacy: VideoPrivacy.PUBLIC - } + { + const frCaption = videoCaptions.find(caption => caption.language.id === 'fr') + expect(frCaption).to.exist + expect(frCaption.language.label).to.equal('French') + expect(frCaption.captionPath).to.match(new RegExp(`^/lazy-static/video-captions/.+-fr.vtt`)) - { - const attributes = { ...baseAttributes, targetUrl: ImportsCommand.getYoutubeVideoUrl() } - const { video } = await servers[0].imports.importVideo({ attributes }) - expect(video.name).to.equal('small video - youtube') + const regex = `WEBVTT[ \n]+Kind: captions[ \n]+` + + `(Language: fr[ \n]+)?` + + `00:00:01.600 --> 00:00:04.200( position:\\d+% line:\\d+%)?[ \n]+Français \\(FR\\)[ \n]+` + + `00:00:05.900 --> 00:00:07.999( position:\\d+% line:\\d+%)?[ \n]+C'est un sous-titre français[ \n]+` + + `00:00:10.000 --> 00:00:14.000( position:\\d+% line:\\d+%)?[ \n]+Ajouter un sous-titre est vraiment facile` - expect(video.thumbnailPath).to.match(new RegExp(`^/static/thumbnails/.+.jpg$`)) - expect(video.previewPath).to.match(new RegExp(`^/lazy-static/previews/.+.jpg$`)) + await testCaptionFile(servers[0].url, frCaption.captionPath, new RegExp(regex)) + } + } - await testImage(servers[0].url, 'video_import_thumbnail', video.thumbnailPath) - await testImage(servers[0].url, 'video_import_preview', video.previewPath) + { + const attributes = { + ...baseAttributes, + magnetUri: FIXTURE_URLS.magnet, + description: 'this is a super torrent description', + tags: [ 'tag_torrent1', 'tag_torrent2' ] + } + const { video } = await servers[0].imports.importVideo({ attributes }) + expect(video.name).to.equal('super peertube2 video') + } - const bodyCaptions = await servers[0].captions.listVideoCaptions({ videoId: video.id }) - const videoCaptions = bodyCaptions.data - expect(videoCaptions).to.have.lengthOf(2) + { + const attributes = { + ...baseAttributes, + torrentfile: 'video-720p.torrent' as any, + description: 'this is a super torrent description', + tags: [ 'tag_torrent1', 'tag_torrent2' ] + } + const { video } = await servers[0].imports.importVideo({ attributes }) + expect(video.name).to.equal('你好 世界 720p.mp4') + } + }) - const enCaption = videoCaptions.find(caption => caption.language.id === 'en') - expect(enCaption).to.exist - expect(enCaption.language.label).to.equal('English') - expect(enCaption.captionPath).to.match(new RegExp(`^/lazy-static/video-captions/.+-en.vtt$`)) - await testCaptionFile(servers[0].url, enCaption.captionPath, `WEBVTT -Kind: captions -Language: en + it('Should list the videos to import in my videos on server 1', async function () { + const { total, data } = await servers[0].videos.listMyVideos({ sort: 'createdAt' }) -00:00:01.600 --> 00:00:04.200 -English (US) + expect(total).to.equal(3) -00:00:05.900 --> 00:00:07.999 -This is a subtitle in American English + expect(data).to.have.lengthOf(3) + expect(data[0].name).to.equal('small video - youtube') + expect(data[1].name).to.equal('super peertube2 video') + expect(data[2].name).to.equal('你好 世界 720p.mp4') + }) -00:00:10.000 --> 00:00:14.000 -Adding subtitles is very easy to do`) + it('Should list the videos to import in my imports on server 1', async function () { + const { total, data: videoImports } = await servers[0].imports.getMyVideoImports({ sort: '-createdAt' }) + expect(total).to.equal(3) - const frCaption = videoCaptions.find(caption => caption.language.id === 'fr') - expect(frCaption).to.exist - expect(frCaption.language.label).to.equal('French') - expect(frCaption.captionPath).to.match(new RegExp(`^/lazy-static/video-captions/.+-fr.vtt`)) - await testCaptionFile(servers[0].url, frCaption.captionPath, `WEBVTT -Kind: captions -Language: fr + expect(videoImports).to.have.lengthOf(3) -00:00:01.600 --> 00:00:04.200 -Français (FR) + expect(videoImports[2].targetUrl).to.equal(FIXTURE_URLS.youtube) + expect(videoImports[2].magnetUri).to.be.null + expect(videoImports[2].torrentName).to.be.null + expect(videoImports[2].video.name).to.equal('small video - youtube') -00:00:05.900 --> 00:00:07.999 -C'est un sous-titre français + expect(videoImports[1].targetUrl).to.be.null + expect(videoImports[1].magnetUri).to.equal(FIXTURE_URLS.magnet) + expect(videoImports[1].torrentName).to.be.null + expect(videoImports[1].video.name).to.equal('super peertube2 video') -00:00:10.000 --> 00:00:14.000 -Ajouter un sous-titre est vraiment facile`) - } + expect(videoImports[0].targetUrl).to.be.null + expect(videoImports[0].magnetUri).to.be.null + expect(videoImports[0].torrentName).to.equal('video-720p.torrent') + expect(videoImports[0].video.name).to.equal('你好 世界 720p.mp4') + }) - { - const attributes = { - ...baseAttributes, - magnetUri: ImportsCommand.getMagnetURI(), - description: 'this is a super torrent description', - tags: [ 'tag_torrent1', 'tag_torrent2' ] - } - const { video } = await servers[0].imports.importVideo({ attributes }) - expect(video.name).to.equal('super peertube2 video') - } + it('Should filter my imports on target URL', async function () { + const { total, data: videoImports } = await servers[0].imports.getMyVideoImports({ targetUrl: FIXTURE_URLS.youtube }) + expect(total).to.equal(1) + expect(videoImports).to.have.lengthOf(1) - { - const attributes = { - ...baseAttributes, - torrentfile: 'video-720p.torrent' as any, - description: 'this is a super torrent description', - tags: [ 'tag_torrent1', 'tag_torrent2' ] - } - const { video } = await servers[0].imports.importVideo({ attributes }) - expect(video.name).to.equal('你好 世界 720p.mp4') - } - }) + expect(videoImports[0].targetUrl).to.equal(FIXTURE_URLS.youtube) + }) - it('Should list the videos to import in my videos on server 1', async function () { - const { total, data } = await servers[0].videos.listMyVideos({ sort: 'createdAt' }) + it('Should search in my imports', async function () { + const { total, data: videoImports } = await servers[0].imports.getMyVideoImports({ search: 'peertube2' }) + expect(total).to.equal(1) + expect(videoImports).to.have.lengthOf(1) - expect(total).to.equal(3) + expect(videoImports[0].magnetUri).to.equal(FIXTURE_URLS.magnet) + expect(videoImports[0].video.name).to.equal('super peertube2 video') + }) - expect(data).to.have.lengthOf(3) - expect(data[0].name).to.equal('small video - youtube') - expect(data[1].name).to.equal('super peertube2 video') - expect(data[2].name).to.equal('你好 世界 720p.mp4') - }) + it('Should have the video listed on the two instances', async function () { + this.timeout(120_000) - it('Should list the videos to import in my imports on server 1', async function () { - const { total, data: videoImports } = await servers[0].imports.getMyVideoImports({ sort: '-createdAt' }) - expect(total).to.equal(3) + await waitJobs(servers) - expect(videoImports).to.have.lengthOf(3) + for (const server of servers) { + const { total, data } = await server.videos.list() + expect(total).to.equal(3) + expect(data).to.have.lengthOf(3) - expect(videoImports[2].targetUrl).to.equal(ImportsCommand.getYoutubeVideoUrl()) - expect(videoImports[2].magnetUri).to.be.null - expect(videoImports[2].torrentName).to.be.null - expect(videoImports[2].video.name).to.equal('small video - youtube') + const [ videoHttp, videoMagnet, videoTorrent ] = data + await checkVideosServer1(server, videoHttp.uuid, videoMagnet.uuid, videoTorrent.uuid) + } + }) + + it('Should import a video on server 2 with some fields', async function () { + this.timeout(60_000) + + const attributes = { + targetUrl: FIXTURE_URLS.youtube, + channelId: servers[1].store.channel.id, + privacy: VideoPrivacy.PUBLIC, + category: 10, + licence: 7, + language: 'en', + name: 'my super name', + description: 'my super description', + tags: [ 'supertag1', 'supertag2' ] + } + const { video } = await servers[1].imports.importVideo({ attributes }) + expect(video.name).to.equal('my super name') + }) - expect(videoImports[1].targetUrl).to.be.null - expect(videoImports[1].magnetUri).to.equal(ImportsCommand.getMagnetURI()) - expect(videoImports[1].torrentName).to.be.null - expect(videoImports[1].video.name).to.equal('super peertube2 video') + it('Should have the videos listed on the two instances', async function () { + this.timeout(120_000) - expect(videoImports[0].targetUrl).to.be.null - expect(videoImports[0].magnetUri).to.be.null - expect(videoImports[0].torrentName).to.equal('video-720p.torrent') - expect(videoImports[0].video.name).to.equal('你好 世界 720p.mp4') - }) + await waitJobs(servers) - it('Should have the video listed on the two instances', async function () { - this.timeout(120_000) + for (const server of servers) { + const { total, data } = await server.videos.list() + expect(total).to.equal(4) + expect(data).to.have.lengthOf(4) - await waitJobs(servers) + await checkVideoServer2(server, data[0].uuid) - for (const server of servers) { - const { total, data } = await server.videos.list() - expect(total).to.equal(3) - expect(data).to.have.lengthOf(3) + const [ , videoHttp, videoMagnet, videoTorrent ] = data + await checkVideosServer1(server, videoHttp.uuid, videoMagnet.uuid, videoTorrent.uuid) + } + }) - const [ videoHttp, videoMagnet, videoTorrent ] = data - await checkVideosServer1(server, videoHttp.uuid, videoMagnet.uuid, videoTorrent.uuid) - } - }) + it('Should import a video that will be transcoded', async function () { + this.timeout(240_000) - it('Should import a video on server 2 with some fields', async function () { - this.timeout(60_000) - - const attributes = { - targetUrl: ImportsCommand.getYoutubeVideoUrl(), - channelId: channelIdServer2, - privacy: VideoPrivacy.PUBLIC, - category: 10, - licence: 7, - language: 'en', - name: 'my super name', - description: 'my super description', - tags: [ 'supertag1', 'supertag2' ] - } - const { video } = await servers[1].imports.importVideo({ attributes }) - expect(video.name).to.equal('my super name') - }) + const attributes = { + name: 'transcoded video', + magnetUri: FIXTURE_URLS.magnet, + channelId: servers[1].store.channel.id, + privacy: VideoPrivacy.PUBLIC + } + const { video } = await servers[1].imports.importVideo({ attributes }) + const videoUUID = video.uuid - it('Should have the videos listed on the two instances', async function () { - this.timeout(120_000) + await waitJobs(servers) - await waitJobs(servers) + for (const server of servers) { + const video = await server.videos.get({ id: videoUUID }) - for (const server of servers) { - const { total, data } = await server.videos.list() - expect(total).to.equal(4) - expect(data).to.have.lengthOf(4) + expect(video.name).to.equal('transcoded video') + expect(video.files).to.have.lengthOf(4) + } + }) + + it('Should import no HDR version on a HDR video', async function () { + this.timeout(300_000) + + const config: DeepPartial = { + transcoding: { + enabled: true, + resolutions: { + '0p': false, + '144p': true, + '240p': true, + '360p': false, + '480p': false, + '720p': false, + '1080p': false, // the resulting resolution shouldn't be higher than this, and not vp9.2/av01 + '1440p': false, + '2160p': false + }, + webtorrent: { enabled: true }, + hls: { enabled: false } + } + } + await servers[0].config.updateExistingSubConfig({ newConfig: config }) - await checkVideoServer2(server, data[0].uuid) + const attributes = { + name: 'hdr video', + targetUrl: FIXTURE_URLS.youtubeHDR, + channelId: servers[0].store.channel.id, + privacy: VideoPrivacy.PUBLIC + } + const { video: videoImported } = await servers[0].imports.importVideo({ attributes }) + const videoUUID = videoImported.uuid + + await waitJobs(servers) + + // test resolution + const video = await servers[0].videos.get({ id: videoUUID }) + expect(video.name).to.equal('hdr video') + const maxResolution = Math.max.apply(Math, video.files.map(function (o) { return o.resolution.id })) + expect(maxResolution, 'expected max resolution not met').to.equals(VideoResolution.H_240P) + }) + + it('Should not import resolution higher than enabled transcoding resolution', async function () { + this.timeout(300_000) + + const config: DeepPartial = { + transcoding: { + enabled: true, + resolutions: { + '0p': false, + '144p': true, + '240p': false, + '360p': false, + '480p': false, + '720p': false, + '1080p': false, + '1440p': false, + '2160p': false + }, + alwaysTranscodeOriginalResolution: false + } + } + await servers[0].config.updateExistingSubConfig({ newConfig: config }) - const [ , videoHttp, videoMagnet, videoTorrent ] = data - await checkVideosServer1(server, videoHttp.uuid, videoMagnet.uuid, videoTorrent.uuid) - } - }) + const attributes = { + name: 'small resolution video', + targetUrl: FIXTURE_URLS.youtube, + channelId: servers[0].store.channel.id, + privacy: VideoPrivacy.PUBLIC + } + const { video: videoImported } = await servers[0].imports.importVideo({ attributes }) + const videoUUID = videoImported.uuid - it('Should import a video that will be transcoded', async function () { - this.timeout(120_000) + await waitJobs(servers) - const attributes = { - name: 'transcoded video', - magnetUri: ImportsCommand.getMagnetURI(), - channelId: channelIdServer2, - privacy: VideoPrivacy.PUBLIC - } - const { video } = await servers[1].imports.importVideo({ attributes }) - const videoUUID = video.uuid + // test resolution + const video = await servers[0].videos.get({ id: videoUUID }) + expect(video.name).to.equal('small resolution video') + expect(video.files).to.have.lengthOf(1) + expect(video.files[0].resolution.id).to.equal(144) + }) - await waitJobs(servers) + it('Should import resolution higher than enabled transcoding resolution', async function () { + this.timeout(300_000) - for (const server of servers) { - const video = await server.videos.get({ id: videoUUID }) + const config: DeepPartial = { + transcoding: { + alwaysTranscodeOriginalResolution: true + } + } + await servers[0].config.updateExistingSubConfig({ newConfig: config }) - expect(video.name).to.equal('transcoded video') - expect(video.files).to.have.lengthOf(4) - } - }) + const attributes = { + name: 'bigger resolution video', + targetUrl: FIXTURE_URLS.youtube, + channelId: servers[0].store.channel.id, + privacy: VideoPrivacy.PUBLIC + } + const { video: videoImported } = await servers[0].imports.importVideo({ attributes }) + const videoUUID = videoImported.uuid + + await waitJobs(servers) + + // test resolution + const video = await servers[0].videos.get({ id: videoUUID }) + expect(video.name).to.equal('bigger resolution video') - it('Should import no HDR version on a HDR video', async function () { - this.timeout(120_000) - - const config = { - transcoding: { - enabled: true, - resolutions: { - '240p': false, - '360p': false, - '480p': false, - '720p': false, - '1080p': true, // the resulting resolution shouldn't be higher than this, and not vp9.2/av01 - '1440p': false, - '2160p': false - }, - webtorrent: { enabled: true }, - hls: { enabled: false } - }, - import: { - videos: { - http: { - enabled: true - }, - torrent: { - enabled: true + expect(video.files).to.have.lengthOf(2) + expect(video.files.find(f => f.resolution.id === 240)).to.exist + expect(video.files.find(f => f.resolution.id === 144)).to.exist + }) + + it('Should import a peertube video', async function () { + this.timeout(120_000) + + const toTest = [ FIXTURE_URLS.peertube_long ] + + // TODO: include peertube_short when https://github.com/ytdl-org/youtube-dl/pull/29475 is merged + if (mode === 'yt-dlp') { + toTest.push(FIXTURE_URLS.peertube_short) + } + + for (const targetUrl of toTest) { + await servers[0].config.disableTranscoding() + + const attributes = { + targetUrl, + channelId: servers[0].store.channel.id, + privacy: VideoPrivacy.PUBLIC + } + const { video } = await servers[0].imports.importVideo({ attributes }) + const videoUUID = video.uuid + + await waitJobs(servers) + + for (const server of servers) { + const video = await server.videos.get({ id: videoUUID }) + + expect(video.name).to.equal('E2E tests') } } + }) + + after(async function () { + await cleanupTests(servers) + }) + }) + } + + runSuite('youtube-dl') + + runSuite('yt-dlp') + + describe('Delete/cancel an import', function () { + let server: PeerTubeServer + + let finishedImportId: number + let finishedVideo: Video + let pendingImportId: number + + async function importVideo (name: string) { + const attributes = { name, channelId: server.store.channel.id, targetUrl: FIXTURE_URLS.goodVideo } + const res = await server.imports.importVideo({ attributes }) + + return res.id + } + + before(async function () { + this.timeout(120_000) + + server = await createSingleServer(1) + + await setAccessTokensToServers([ server ]) + await setDefaultVideoChannel([ server ]) + + finishedImportId = await importVideo('finished') + await waitJobs([ server ]) + + await server.jobs.pauseJobQueue() + pendingImportId = await importVideo('pending') + + const { data } = await server.imports.getMyVideoImports() + expect(data).to.have.lengthOf(2) + + finishedVideo = data.find(i => i.id === finishedImportId).video + }) + + it('Should delete a video import', async function () { + await server.imports.delete({ importId: finishedImportId }) + + const { data } = await server.imports.getMyVideoImports() + expect(data).to.have.lengthOf(1) + expect(data[0].id).to.equal(pendingImportId) + expect(data[0].state.id).to.equal(VideoImportState.PENDING) + }) + + it('Should not have deleted the associated video', async function () { + const video = await server.videos.get({ id: finishedVideo.id, token: server.accessToken, expectedStatus: HttpStatusCode.OK_200 }) + expect(video.name).to.equal('finished') + expect(video.state.id).to.equal(VideoState.PUBLISHED) + }) + + it('Should cancel a video import', async function () { + await server.imports.cancel({ importId: pendingImportId }) + + const { data } = await server.imports.getMyVideoImports() + expect(data).to.have.lengthOf(1) + expect(data[0].id).to.equal(pendingImportId) + expect(data[0].state.id).to.equal(VideoImportState.CANCELLED) + }) + + it('Should not have processed the cancelled video import', async function () { + this.timeout(60_000) + + await server.jobs.resumeJobQueue() + + await waitJobs([ server ]) + + const { data } = await server.imports.getMyVideoImports() + expect(data).to.have.lengthOf(1) + expect(data[0].id).to.equal(pendingImportId) + expect(data[0].state.id).to.equal(VideoImportState.CANCELLED) + expect(data[0].video.state.id).to.equal(VideoState.TO_IMPORT) + }) + + it('Should delete the cancelled video import', async function () { + await server.imports.delete({ importId: pendingImportId }) + const { data } = await server.imports.getMyVideoImports() + expect(data).to.have.lengthOf(0) + }) + + after(async function () { + await cleanupTests([ server ]) + }) + }) + + describe('Auto update', function () { + let server: PeerTubeServer + + function quickPeerTubeImport () { + const attributes = { + targetUrl: FIXTURE_URLS.peertube_long, + channelId: server.store.channel.id, + privacy: VideoPrivacy.PUBLIC } + + return server.imports.importVideo({ attributes }) } - await servers[0].config.updateCustomSubConfig({ newConfig: config }) - const attributes = { - name: 'hdr video', - targetUrl: ImportsCommand.getYoutubeHDRVideoUrl(), - channelId: channelIdServer1, - privacy: VideoPrivacy.PUBLIC + async function testBinaryUpdate (releaseUrl: string, releaseName: string) { + await remove(join(server.servers.buildDirectory('bin'), releaseName)) + + await server.kill() + await server.run({ + import: { + videos: { + http: { + youtube_dl_release: { + url: releaseUrl, + name: releaseName + } + } + } + } + }) + + await quickPeerTubeImport() + + const base = server.servers.buildDirectory('bin') + const content = await readdir(base) + const binaryPath = join(base, releaseName) + + expect(await pathExists(binaryPath), `${binaryPath} does not exist in ${base} (${content.join(', ')})`).to.be.true } - const { video: videoImported } = await servers[0].imports.importVideo({ attributes }) - const videoUUID = videoImported.uuid - await waitJobs(servers) + before(async function () { + this.timeout(30_000) - // test resolution - const video = await servers[0].videos.get({ id: videoUUID }) - expect(video.name).to.equal('hdr video') - const maxResolution = Math.max.apply(Math, video.files.map(function (o) { return o.resolution.id })) - expect(maxResolution, 'expected max resolution not met').to.equals(VideoResolution.H_1080P) - }) + // Run servers + server = await createSingleServer(1) + + await setAccessTokensToServers([ server ]) + await setDefaultVideoChannel([ server ]) + }) + + it('Should update youtube-dl from github URL', async function () { + this.timeout(120_000) + + await testBinaryUpdate('https://api.github.com/repos/ytdl-org/youtube-dl/releases', 'youtube-dl') + }) + + it('Should update youtube-dl from raw URL', async function () { + this.timeout(120_000) + + await testBinaryUpdate('https://yt-dl.org/downloads/latest/youtube-dl', 'youtube-dl') + }) + + it('Should update youtube-dl from youtube-dl fork', async function () { + this.timeout(120_000) + + await testBinaryUpdate('https://api.github.com/repos/yt-dlp/yt-dlp/releases', 'yt-dlp') + }) - after(async function () { - await cleanupTests(servers) + after(async function () { + await cleanupTests([ server ]) + }) }) })