mirror of https://github.com/Chocobozzz/PeerTube
Optimize fetching playlist urls
parent
d4d9bbc6f2
commit
e9fc9e03c1
|
@ -142,6 +142,11 @@ export class YoutubeDLCLI {
|
||||||
}): Promise<{ upload_date: string, webpage_url: string }[]> {
|
}): Promise<{ upload_date: string, webpage_url: string }[]> {
|
||||||
const additionalYoutubeDLArgs = [ '--skip-download', '--playlist-reverse' ]
|
const additionalYoutubeDLArgs = [ '--skip-download', '--playlist-reverse' ]
|
||||||
|
|
||||||
|
if (CONFIG.IMPORT.VIDEOS.HTTP.YOUTUBE_DL_RELEASE.NAME === 'yt-dlp') {
|
||||||
|
// Optimize listing videos only when using yt-dlp because it is bugged with youtube-dl when fetching a channel
|
||||||
|
additionalYoutubeDLArgs.push('--flat-playlist')
|
||||||
|
}
|
||||||
|
|
||||||
if (options.latestVideosCount !== undefined) {
|
if (options.latestVideosCount !== undefined) {
|
||||||
additionalYoutubeDLArgs.push('--playlist-end', options.latestVideosCount.toString())
|
additionalYoutubeDLArgs.push('--playlist-end', options.latestVideosCount.toString())
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import { move, pathExists, readdir, remove } from 'fs-extra'
|
import { move, pathExists, readdir, remove } from 'fs-extra'
|
||||||
import { dirname, join } from 'path'
|
import { dirname, join } from 'path'
|
||||||
|
import { inspect } from 'util'
|
||||||
import { CONFIG } from '@server/initializers/config'
|
import { CONFIG } from '@server/initializers/config'
|
||||||
import { isVideoFileExtnameValid } from '../custom-validators/videos'
|
import { isVideoFileExtnameValid } from '../custom-validators/videos'
|
||||||
import { logger, loggerTagsFactory } from '../logger'
|
import { logger, loggerTagsFactory } from '../logger'
|
||||||
|
@ -59,13 +60,9 @@ class YoutubeDLWrapper {
|
||||||
processOptions
|
processOptions
|
||||||
})
|
})
|
||||||
|
|
||||||
if (!Array.isArray(list)) throw new Error(`YoutubeDL could not get list info from ${this.url}`)
|
if (!Array.isArray(list)) throw new Error(`YoutubeDL could not get list info from ${this.url}: ${inspect(list)}`)
|
||||||
|
|
||||||
return list.map(info => {
|
return list.map(info => info.webpage_url)
|
||||||
const infoBuilder = new YoutubeDLInfoBuilder(info)
|
|
||||||
|
|
||||||
return infoBuilder.getInfo()
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async getSubtitles (): Promise<YoutubeDLSubs> {
|
async getSubtitles (): Promise<YoutubeDLSubs> {
|
||||||
|
|
|
@ -4,7 +4,7 @@ import { CONFIG } from '@server/initializers/config'
|
||||||
import { buildYoutubeDLImport } from '@server/lib/video-import'
|
import { buildYoutubeDLImport } from '@server/lib/video-import'
|
||||||
import { UserModel } from '@server/models/user/user'
|
import { UserModel } from '@server/models/user/user'
|
||||||
import { VideoImportModel } from '@server/models/video/video-import'
|
import { VideoImportModel } from '@server/models/video/video-import'
|
||||||
import { MChannelAccountDefault, MChannelSync } from '@server/types/models'
|
import { MChannel, MChannelAccountDefault, MChannelSync } from '@server/types/models'
|
||||||
import { VideoChannelSyncState, VideoPrivacy } from '@shared/models'
|
import { VideoChannelSyncState, VideoPrivacy } from '@shared/models'
|
||||||
import { CreateJobArgument, JobQueue } from './job-queue'
|
import { CreateJobArgument, JobQueue } from './job-queue'
|
||||||
import { ServerConfigManager } from './server-config-manager'
|
import { ServerConfigManager } from './server-config-manager'
|
||||||
|
@ -31,15 +31,7 @@ export async function synchronizeChannel (options: {
|
||||||
CONFIG.TRANSCODING.ALWAYS_TRANSCODE_ORIGINAL_RESOLUTION
|
CONFIG.TRANSCODING.ALWAYS_TRANSCODE_ORIGINAL_RESOLUTION
|
||||||
)
|
)
|
||||||
|
|
||||||
const infoList = await youtubeDL.getInfoForListImport({ latestVideosCount: videosCountLimit })
|
const targetUrls = await youtubeDL.getInfoForListImport({ latestVideosCount: videosCountLimit })
|
||||||
|
|
||||||
const targetUrls = infoList
|
|
||||||
.filter(videoInfo => {
|
|
||||||
if (!onlyAfter) return true
|
|
||||||
|
|
||||||
return videoInfo.originallyPublishedAt.getTime() >= onlyAfter.getTime()
|
|
||||||
})
|
|
||||||
.map(videoInfo => videoInfo.webpageUrl)
|
|
||||||
|
|
||||||
logger.info(
|
logger.info(
|
||||||
'Fetched %d candidate URLs for sync channel %s.',
|
'Fetched %d candidate URLs for sync channel %s.',
|
||||||
|
@ -58,10 +50,7 @@ export async function synchronizeChannel (options: {
|
||||||
const children: CreateJobArgument[] = []
|
const children: CreateJobArgument[] = []
|
||||||
|
|
||||||
for (const targetUrl of targetUrls) {
|
for (const targetUrl of targetUrls) {
|
||||||
if (await VideoImportModel.urlAlreadyImported(channel.id, targetUrl)) {
|
if (await skipImport(channel, targetUrl, onlyAfter)) continue
|
||||||
logger.debug('%s is already imported for channel %s, skipping video channel synchronization.', channel.name, targetUrl)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
const { job } = await buildYoutubeDLImport({
|
const { job } = await buildYoutubeDLImport({
|
||||||
user,
|
user,
|
||||||
|
@ -86,3 +75,28 @@ export async function synchronizeChannel (options: {
|
||||||
|
|
||||||
await JobQueue.Instance.createJobWithChildren(parent, children)
|
await JobQueue.Instance.createJobWithChildren(parent, children)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
async function skipImport (channel: MChannel, targetUrl: string, onlyAfter?: Date) {
|
||||||
|
if (await VideoImportModel.urlAlreadyImported(channel.id, targetUrl)) {
|
||||||
|
logger.debug('%s is already imported for channel %s, skipping video channel synchronization.', channel.name, targetUrl)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
if (onlyAfter) {
|
||||||
|
const youtubeDL = new YoutubeDLWrapper(
|
||||||
|
targetUrl,
|
||||||
|
ServerConfigManager.Instance.getEnabledResolutions('vod'),
|
||||||
|
CONFIG.TRANSCODING.ALWAYS_TRANSCODE_ORIGINAL_RESOLUTION
|
||||||
|
)
|
||||||
|
|
||||||
|
const videoInfo = await youtubeDL.getInfoForDownload()
|
||||||
|
|
||||||
|
if (videoInfo.originallyPublishedAt.getTime() < onlyAfter.getTime()) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
|
@ -1021,7 +1021,7 @@ describe('Test multiple servers', function () {
|
||||||
|
|
||||||
describe('With minimum parameters', function () {
|
describe('With minimum parameters', function () {
|
||||||
it('Should upload and propagate the video', async function () {
|
it('Should upload and propagate the video', async function () {
|
||||||
this.timeout(60000)
|
this.timeout(120000)
|
||||||
|
|
||||||
const path = '/api/v1/videos/upload'
|
const path = '/api/v1/videos/upload'
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue