mirror of
https://github.com/Chocobozzz/PeerTube.git
synced 2025-02-25 18:55:32 -06:00
Prefer web videos in favour of webtorrent
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
import express from 'express'
|
||||
import { logger, loggerTagsFactory } from '@server/helpers/logger'
|
||||
import { proxifyHLS, proxifyWebTorrentFile } from '@server/lib/object-storage'
|
||||
import { proxifyHLS, proxifyWebVideoFile } from '@server/lib/object-storage'
|
||||
import { VideoPathManager } from '@server/lib/video-path-manager'
|
||||
import { getStudioTaskFilePath } from '@server/lib/video-studio'
|
||||
import { apiRateLimiter, asyncMiddleware } from '@server/middlewares'
|
||||
@@ -70,7 +70,7 @@ async function getMaxQualityVideoFile (req: express.Request, res: express.Respon
|
||||
}
|
||||
|
||||
// Web video
|
||||
return proxifyWebTorrentFile({
|
||||
return proxifyWebVideoFile({
|
||||
req,
|
||||
res,
|
||||
filename: file.filename
|
||||
|
||||
@@ -213,19 +213,14 @@ async function updateMe (req: express.Request, res: express.Response) {
|
||||
'noInstanceConfigWarningModal',
|
||||
'noAccountSetupWarningModal',
|
||||
'noWelcomeModal',
|
||||
'emailPublic'
|
||||
'emailPublic',
|
||||
'p2pEnabled'
|
||||
]
|
||||
|
||||
for (const key of keysToUpdate) {
|
||||
if (body[key] !== undefined) user.set(key, body[key])
|
||||
}
|
||||
|
||||
if (body.p2pEnabled !== undefined) {
|
||||
user.set('p2pEnabled', body.p2pEnabled)
|
||||
} else if (body.webTorrentEnabled !== undefined) { // FIXME: deprecated in 4.1
|
||||
user.set('p2pEnabled', body.webTorrentEnabled)
|
||||
}
|
||||
|
||||
if (body.email !== undefined) {
|
||||
if (CONFIG.SIGNUP.REQUIRES_EMAIL_VERIFICATION) {
|
||||
user.pendingEmail = body.email
|
||||
|
||||
@@ -2,7 +2,8 @@ import express from 'express'
|
||||
import toInt from 'validator/lib/toInt'
|
||||
import { logger, loggerTagsFactory } from '@server/helpers/logger'
|
||||
import { federateVideoIfNeeded } from '@server/lib/activitypub/videos'
|
||||
import { removeAllWebTorrentFiles, removeHLSFile, removeHLSPlaylist, removeWebTorrentFile } from '@server/lib/video-file'
|
||||
import { updatePlaylistAfterFileChange } from '@server/lib/hls'
|
||||
import { removeAllWebVideoFiles, removeHLSFile, removeHLSPlaylist, removeWebVideoFile } from '@server/lib/video-file'
|
||||
import { VideoFileModel } from '@server/models/video/video-file'
|
||||
import { HttpStatusCode, UserRight } from '@shared/models'
|
||||
import {
|
||||
@@ -12,11 +13,10 @@ import {
|
||||
videoFileMetadataGetValidator,
|
||||
videoFilesDeleteHLSFileValidator,
|
||||
videoFilesDeleteHLSValidator,
|
||||
videoFilesDeleteWebTorrentFileValidator,
|
||||
videoFilesDeleteWebTorrentValidator,
|
||||
videoFilesDeleteWebVideoFileValidator,
|
||||
videoFilesDeleteWebVideoValidator,
|
||||
videosGetValidator
|
||||
} from '../../../middlewares'
|
||||
import { updatePlaylistAfterFileChange } from '@server/lib/hls'
|
||||
|
||||
const lTags = loggerTagsFactory('api', 'video')
|
||||
const filesRouter = express.Router()
|
||||
@@ -40,17 +40,19 @@ filesRouter.delete('/:id/hls/:videoFileId',
|
||||
asyncMiddleware(removeHLSFileController)
|
||||
)
|
||||
|
||||
filesRouter.delete('/:id/webtorrent',
|
||||
filesRouter.delete(
|
||||
[ '/:id/webtorrent', '/:id/web-videos' ], // TODO: remove webtorrent in V7
|
||||
authenticate,
|
||||
ensureUserHasRight(UserRight.MANAGE_VIDEO_FILES),
|
||||
asyncMiddleware(videoFilesDeleteWebTorrentValidator),
|
||||
asyncMiddleware(removeAllWebTorrentFilesController)
|
||||
asyncMiddleware(videoFilesDeleteWebVideoValidator),
|
||||
asyncMiddleware(removeAllWebVideoFilesController)
|
||||
)
|
||||
filesRouter.delete('/:id/webtorrent/:videoFileId',
|
||||
filesRouter.delete(
|
||||
[ '/:id/webtorrent/:videoFileId', '/:id/web-videos/:videoFileId' ], // TODO: remove webtorrent in V7
|
||||
authenticate,
|
||||
ensureUserHasRight(UserRight.MANAGE_VIDEO_FILES),
|
||||
asyncMiddleware(videoFilesDeleteWebTorrentFileValidator),
|
||||
asyncMiddleware(removeWebTorrentFileController)
|
||||
asyncMiddleware(videoFilesDeleteWebVideoFileValidator),
|
||||
asyncMiddleware(removeWebVideoFileController)
|
||||
)
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
@@ -96,24 +98,24 @@ async function removeHLSFileController (req: express.Request, res: express.Respo
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
async function removeAllWebTorrentFilesController (req: express.Request, res: express.Response) {
|
||||
async function removeAllWebVideoFilesController (req: express.Request, res: express.Response) {
|
||||
const video = res.locals.videoAll
|
||||
|
||||
logger.info('Deleting WebTorrent files of %s.', video.url, lTags(video.uuid))
|
||||
logger.info('Deleting Web Video files of %s.', video.url, lTags(video.uuid))
|
||||
|
||||
await removeAllWebTorrentFiles(video)
|
||||
await removeAllWebVideoFiles(video)
|
||||
await federateVideoIfNeeded(video, false, undefined)
|
||||
|
||||
return res.sendStatus(HttpStatusCode.NO_CONTENT_204)
|
||||
}
|
||||
|
||||
async function removeWebTorrentFileController (req: express.Request, res: express.Response) {
|
||||
async function removeWebVideoFileController (req: express.Request, res: express.Response) {
|
||||
const video = res.locals.videoAll
|
||||
|
||||
const videoFileId = +req.params.videoFileId
|
||||
logger.info('Deleting WebTorrent file %d of %s.', videoFileId, video.url, lTags(video.uuid))
|
||||
logger.info('Deleting Web Video file %d of %s.', videoFileId, video.url, lTags(video.uuid))
|
||||
|
||||
await removeWebTorrentFile(video, videoFileId)
|
||||
await removeWebVideoFile(video, videoFileId)
|
||||
await federateVideoIfNeeded(video, false, undefined)
|
||||
|
||||
return res.sendStatus(HttpStatusCode.NO_CONTENT_204)
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import cors from 'cors'
|
||||
import express from 'express'
|
||||
import { OBJECT_STORAGE_PROXY_PATHS } from '@server/initializers/constants'
|
||||
import { proxifyHLS, proxifyWebTorrentFile } from '@server/lib/object-storage'
|
||||
import { proxifyHLS, proxifyWebVideoFile } from '@server/lib/object-storage'
|
||||
import {
|
||||
asyncMiddleware,
|
||||
ensureCanAccessPrivateVideoHLSFiles,
|
||||
ensureCanAccessVideoPrivateWebTorrentFiles,
|
||||
ensureCanAccessVideoPrivateWebVideoFiles,
|
||||
ensurePrivateObjectStorageProxyIsEnabled,
|
||||
optionalAuthenticate
|
||||
} from '@server/middlewares'
|
||||
@@ -18,8 +18,8 @@ objectStorageProxyRouter.use(cors())
|
||||
objectStorageProxyRouter.get(OBJECT_STORAGE_PROXY_PATHS.PRIVATE_WEBSEED + ':filename',
|
||||
ensurePrivateObjectStorageProxyIsEnabled,
|
||||
optionalAuthenticate,
|
||||
asyncMiddleware(ensureCanAccessVideoPrivateWebTorrentFiles),
|
||||
asyncMiddleware(proxifyWebTorrentController)
|
||||
asyncMiddleware(ensureCanAccessVideoPrivateWebVideoFiles),
|
||||
asyncMiddleware(proxifyWebVideoController)
|
||||
)
|
||||
|
||||
objectStorageProxyRouter.get(OBJECT_STORAGE_PROXY_PATHS.STREAMING_PLAYLISTS.PRIVATE_HLS + ':videoUUID/:filename',
|
||||
@@ -35,10 +35,10 @@ export {
|
||||
objectStorageProxyRouter
|
||||
}
|
||||
|
||||
function proxifyWebTorrentController (req: express.Request, res: express.Response) {
|
||||
function proxifyWebVideoController (req: express.Request, res: express.Response) {
|
||||
const filename = req.params.filename
|
||||
|
||||
return proxifyWebTorrentFile({ req, res, filename })
|
||||
return proxifyWebVideoFile({ req, res, filename })
|
||||
}
|
||||
|
||||
function proxifyHLSController (req: express.Request, res: express.Response) {
|
||||
|
||||
@@ -6,7 +6,7 @@ import { injectQueryToPlaylistUrls } from '@server/lib/hls'
|
||||
import {
|
||||
asyncMiddleware,
|
||||
ensureCanAccessPrivateVideoHLSFiles,
|
||||
ensureCanAccessVideoPrivateWebTorrentFiles,
|
||||
ensureCanAccessVideoPrivateWebVideoFiles,
|
||||
handleStaticError,
|
||||
optionalAuthenticate
|
||||
} from '@server/middlewares'
|
||||
@@ -21,16 +21,16 @@ const staticRouter = express.Router()
|
||||
staticRouter.use(cors())
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// WebTorrent/Classic videos
|
||||
// Web videos/Classic videos
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
const privateWebTorrentStaticMiddlewares = CONFIG.STATIC_FILES.PRIVATE_FILES_REQUIRE_AUTH === true
|
||||
? [ optionalAuthenticate, asyncMiddleware(ensureCanAccessVideoPrivateWebTorrentFiles) ]
|
||||
const privateWebVideoStaticMiddlewares = CONFIG.STATIC_FILES.PRIVATE_FILES_REQUIRE_AUTH === true
|
||||
? [ optionalAuthenticate, asyncMiddleware(ensureCanAccessVideoPrivateWebVideoFiles) ]
|
||||
: []
|
||||
|
||||
staticRouter.use(
|
||||
STATIC_PATHS.PRIVATE_WEBSEED,
|
||||
...privateWebTorrentStaticMiddlewares,
|
||||
...privateWebVideoStaticMiddlewares,
|
||||
express.static(DIRECTORIES.VIDEOS.PRIVATE, { fallthrough: false }),
|
||||
handleStaticError
|
||||
)
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
function isValidPlayerMode (value: any) {
|
||||
return value === 'webtorrent' || value === 'p2p-media-loader'
|
||||
// TODO: remove webtorrent in v7
|
||||
return value === 'webtorrent' || value === 'web-video' || value === 'p2p-media-loader'
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
@@ -2,7 +2,7 @@ import { exists } from './misc'
|
||||
|
||||
function isValidCreateTranscodingType (value: any) {
|
||||
return exists(value) &&
|
||||
(value === 'hls' || value === 'webtorrent')
|
||||
(value === 'hls' || value === 'webtorrent' || value === 'web-video') // TODO: remove webtorrent in v7
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
@@ -23,7 +23,8 @@ function pickCommonVideoQuery (query: VideosCommonQueryAfterSanitize) {
|
||||
'include',
|
||||
'skipCount',
|
||||
'hasHLSFiles',
|
||||
'hasWebtorrentFiles',
|
||||
'hasWebtorrentFiles', // TODO: Remove in v7
|
||||
'hasWebVideoFiles',
|
||||
'search',
|
||||
'excludeAlreadyWatched'
|
||||
])
|
||||
|
||||
@@ -199,7 +199,7 @@ function checkStorageConfig () {
|
||||
function checkTranscodingConfig () {
|
||||
if (CONFIG.TRANSCODING.ENABLED) {
|
||||
if (CONFIG.TRANSCODING.WEBTORRENT.ENABLED === false && CONFIG.TRANSCODING.HLS.ENABLED === false) {
|
||||
throw new Error('You need to enable at least WebTorrent transcoding or HLS transcoding.')
|
||||
throw new Error('You need to enable at least Web Video transcoding or HLS transcoding.')
|
||||
}
|
||||
|
||||
if (CONFIG.TRANSCODING.CONCURRENCY <= 0) {
|
||||
|
||||
@@ -126,7 +126,7 @@ export abstract class APVideoAbstractBuilder {
|
||||
video.VideoLive = videoLive
|
||||
}
|
||||
|
||||
protected async setWebTorrentFiles (video: MVideoFullLight, t: Transaction) {
|
||||
protected async setWebVideoFiles (video: MVideoFullLight, t: Transaction) {
|
||||
const videoFileAttributes = getFileAttributesFromUrl(video, this.videoObject.url)
|
||||
const newVideoFiles = videoFileAttributes.map(a => new VideoFileModel(a))
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@ export class APVideoCreator extends APVideoAbstractBuilder {
|
||||
|
||||
await this.setThumbnail(videoCreated, t)
|
||||
await this.setPreview(videoCreated, t)
|
||||
await this.setWebTorrentFiles(videoCreated, t)
|
||||
await this.setWebVideoFiles(videoCreated, t)
|
||||
await this.setStreamingPlaylists(videoCreated, t)
|
||||
await this.setTags(videoCreated, t)
|
||||
await this.setTrackers(videoCreated, t)
|
||||
|
||||
@@ -50,7 +50,7 @@ export class APVideoUpdater extends APVideoAbstractBuilder {
|
||||
if (thumbnailModel) await videoUpdated.addAndSaveThumbnail(thumbnailModel)
|
||||
|
||||
await runInReadCommittedTransaction(async t => {
|
||||
await this.setWebTorrentFiles(videoUpdated, t)
|
||||
await this.setWebVideoFiles(videoUpdated, t)
|
||||
await this.setStreamingPlaylists(videoUpdated, t)
|
||||
})
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ import { join } from 'path'
|
||||
import { logger, loggerTagsFactory } from '@server/helpers/logger'
|
||||
import { updateTorrentMetadata } from '@server/helpers/webtorrent'
|
||||
import { P2P_MEDIA_LOADER_PEER_VERSION } from '@server/initializers/constants'
|
||||
import { storeHLSFileFromFilename, storeWebTorrentFile } from '@server/lib/object-storage'
|
||||
import { storeHLSFileFromFilename, storeWebVideoFile } from '@server/lib/object-storage'
|
||||
import { getHLSDirectory, getHlsResolutionPlaylistFilename } from '@server/lib/paths'
|
||||
import { VideoPathManager } from '@server/lib/video-path-manager'
|
||||
import { moveToFailedMoveToObjectStorageState, moveToNextState } from '@server/lib/video-state'
|
||||
@@ -33,9 +33,9 @@ export async function processMoveToObjectStorage (job: Job) {
|
||||
|
||||
try {
|
||||
if (video.VideoFiles) {
|
||||
logger.debug('Moving %d webtorrent files for video %s.', video.VideoFiles.length, video.uuid, lTags)
|
||||
logger.debug('Moving %d web video files for video %s.', video.VideoFiles.length, video.uuid, lTags)
|
||||
|
||||
await moveWebTorrentFiles(video)
|
||||
await moveWebVideoFiles(video)
|
||||
}
|
||||
|
||||
if (video.VideoStreamingPlaylists) {
|
||||
@@ -75,11 +75,11 @@ export async function onMoveToObjectStorageFailure (job: Job, err: any) {
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
async function moveWebTorrentFiles (video: MVideoWithAllFiles) {
|
||||
async function moveWebVideoFiles (video: MVideoWithAllFiles) {
|
||||
for (const file of video.VideoFiles) {
|
||||
if (file.storage !== VideoStorage.FILE_SYSTEM) continue
|
||||
|
||||
const fileUrl = await storeWebTorrentFile(video, file)
|
||||
const fileUrl = await storeWebVideoFile(video, file)
|
||||
|
||||
const oldPath = VideoPathManager.Instance.getFSVideoFileOutputPath(video, file)
|
||||
await onFileMoved({ videoOrPlaylist: video, file, fileUrl, oldPath })
|
||||
|
||||
@@ -3,7 +3,7 @@ import { copy, stat } from 'fs-extra'
|
||||
import { createTorrentAndSetInfoHash } from '@server/helpers/webtorrent'
|
||||
import { CONFIG } from '@server/initializers/config'
|
||||
import { federateVideoIfNeeded } from '@server/lib/activitypub/videos'
|
||||
import { generateWebTorrentVideoFilename } from '@server/lib/paths'
|
||||
import { generateWebVideoFilename } from '@server/lib/paths'
|
||||
import { buildMoveToObjectStorageJob } from '@server/lib/video'
|
||||
import { VideoPathManager } from '@server/lib/video-path-manager'
|
||||
import { VideoModel } from '@server/models/video/video'
|
||||
@@ -56,7 +56,7 @@ async function updateVideoFile (video: MVideoFullLight, inputFilePath: string) {
|
||||
|
||||
if (currentVideoFile) {
|
||||
// Remove old file and old torrent
|
||||
await video.removeWebTorrentFile(currentVideoFile)
|
||||
await video.removeWebVideoFile(currentVideoFile)
|
||||
// Remove the old video file from the array
|
||||
video.VideoFiles = video.VideoFiles.filter(f => f !== currentVideoFile)
|
||||
|
||||
@@ -66,7 +66,7 @@ async function updateVideoFile (video: MVideoFullLight, inputFilePath: string) {
|
||||
const newVideoFile = new VideoFileModel({
|
||||
resolution,
|
||||
extname: fileExt,
|
||||
filename: generateWebTorrentVideoFilename(resolution, fileExt),
|
||||
filename: generateWebVideoFilename(resolution, fileExt),
|
||||
storage: VideoStorage.FILE_SYSTEM,
|
||||
size,
|
||||
fps,
|
||||
|
||||
@@ -4,7 +4,7 @@ import { retryTransactionWrapper } from '@server/helpers/database-utils'
|
||||
import { YoutubeDLWrapper } from '@server/helpers/youtube-dl'
|
||||
import { CONFIG } from '@server/initializers/config'
|
||||
import { isPostImportVideoAccepted } from '@server/lib/moderation'
|
||||
import { generateWebTorrentVideoFilename } from '@server/lib/paths'
|
||||
import { generateWebVideoFilename } from '@server/lib/paths'
|
||||
import { Hooks } from '@server/lib/plugins/hooks'
|
||||
import { ServerConfigManager } from '@server/lib/server-config-manager'
|
||||
import { createOptimizeOrMergeAudioJobs } from '@server/lib/transcoding/create-transcoding-job'
|
||||
@@ -148,7 +148,7 @@ async function processFile (downloader: () => Promise<string>, videoImport: MVid
|
||||
extname: fileExt,
|
||||
resolution,
|
||||
size: stats.size,
|
||||
filename: generateWebTorrentVideoFilename(resolution, fileExt),
|
||||
filename: generateWebVideoFilename(resolution, fileExt),
|
||||
fps,
|
||||
videoId: videoImport.videoId
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { Job } from 'bullmq'
|
||||
import { onTranscodingEnded } from '@server/lib/transcoding/ended-transcoding'
|
||||
import { generateHlsPlaylistResolution } from '@server/lib/transcoding/hls-transcoding'
|
||||
import { mergeAudioVideofile, optimizeOriginalVideofile, transcodeNewWebTorrentResolution } from '@server/lib/transcoding/web-transcoding'
|
||||
import { removeAllWebTorrentFiles } from '@server/lib/video-file'
|
||||
import { mergeAudioVideofile, optimizeOriginalVideofile, transcodeNewWebVideoResolution } from '@server/lib/transcoding/web-transcoding'
|
||||
import { removeAllWebVideoFiles } from '@server/lib/video-file'
|
||||
import { VideoPathManager } from '@server/lib/video-path-manager'
|
||||
import { moveToFailedTranscodingState } from '@server/lib/video-state'
|
||||
import { UserModel } from '@server/models/user/user'
|
||||
@@ -11,7 +11,7 @@ import { MUser, MUserId, MVideoFullLight } from '@server/types/models'
|
||||
import {
|
||||
HLSTranscodingPayload,
|
||||
MergeAudioTranscodingPayload,
|
||||
NewWebTorrentResolutionTranscodingPayload,
|
||||
NewWebVideoResolutionTranscodingPayload,
|
||||
OptimizeTranscodingPayload,
|
||||
VideoTranscodingPayload
|
||||
} from '@shared/models'
|
||||
@@ -22,9 +22,9 @@ type HandlerFunction = (job: Job, payload: VideoTranscodingPayload, video: MVide
|
||||
|
||||
const handlers: { [ id in VideoTranscodingPayload['type'] ]: HandlerFunction } = {
|
||||
'new-resolution-to-hls': handleHLSJob,
|
||||
'new-resolution-to-webtorrent': handleNewWebTorrentResolutionJob,
|
||||
'merge-audio-to-webtorrent': handleWebTorrentMergeAudioJob,
|
||||
'optimize-to-webtorrent': handleWebTorrentOptimizeJob
|
||||
'new-resolution-to-web-video': handleNewWebVideoResolutionJob,
|
||||
'merge-audio-to-web-video': handleWebVideoMergeAudioJob,
|
||||
'optimize-to-web-video': handleWebVideoOptimizeJob
|
||||
}
|
||||
|
||||
const lTags = loggerTagsFactory('transcoding')
|
||||
@@ -74,7 +74,7 @@ export {
|
||||
// Job handlers
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
async function handleWebTorrentMergeAudioJob (job: Job, payload: MergeAudioTranscodingPayload, video: MVideoFullLight, user: MUserId) {
|
||||
async function handleWebVideoMergeAudioJob (job: Job, payload: MergeAudioTranscodingPayload, video: MVideoFullLight, user: MUserId) {
|
||||
logger.info('Handling merge audio transcoding job for %s.', video.uuid, lTags(video.uuid), { payload })
|
||||
|
||||
await mergeAudioVideofile({ video, resolution: payload.resolution, fps: payload.fps, job })
|
||||
@@ -84,7 +84,7 @@ async function handleWebTorrentMergeAudioJob (job: Job, payload: MergeAudioTrans
|
||||
await onTranscodingEnded({ isNewVideo: payload.isNewVideo, moveVideoToNextState: !payload.hasChildren, video })
|
||||
}
|
||||
|
||||
async function handleWebTorrentOptimizeJob (job: Job, payload: OptimizeTranscodingPayload, video: MVideoFullLight, user: MUserId) {
|
||||
async function handleWebVideoOptimizeJob (job: Job, payload: OptimizeTranscodingPayload, video: MVideoFullLight, user: MUserId) {
|
||||
logger.info('Handling optimize transcoding job for %s.', video.uuid, lTags(video.uuid), { payload })
|
||||
|
||||
await optimizeOriginalVideofile({ video, inputVideoFile: video.getMaxQualityFile(), quickTranscode: payload.quickTranscode, job })
|
||||
@@ -96,12 +96,12 @@ async function handleWebTorrentOptimizeJob (job: Job, payload: OptimizeTranscodi
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
async function handleNewWebTorrentResolutionJob (job: Job, payload: NewWebTorrentResolutionTranscodingPayload, video: MVideoFullLight) {
|
||||
logger.info('Handling WebTorrent transcoding job for %s.', video.uuid, lTags(video.uuid), { payload })
|
||||
async function handleNewWebVideoResolutionJob (job: Job, payload: NewWebVideoResolutionTranscodingPayload, video: MVideoFullLight) {
|
||||
logger.info('Handling Web Video transcoding job for %s.', video.uuid, lTags(video.uuid), { payload })
|
||||
|
||||
await transcodeNewWebTorrentResolution({ video, resolution: payload.resolution, fps: payload.fps, job })
|
||||
await transcodeNewWebVideoResolution({ video, resolution: payload.resolution, fps: payload.fps, job })
|
||||
|
||||
logger.info('WebTorrent transcoding job for %s ended.', video.uuid, lTags(video.uuid), { payload })
|
||||
logger.info('Web Video transcoding job for %s ended.', video.uuid, lTags(video.uuid), { payload })
|
||||
|
||||
await onTranscodingEnded({ isNewVideo: payload.isNewVideo, moveVideoToNextState: true, video })
|
||||
}
|
||||
@@ -118,7 +118,7 @@ async function handleHLSJob (job: Job, payload: HLSTranscodingPayload, videoArg:
|
||||
video = await VideoModel.loadFull(videoArg.uuid)
|
||||
|
||||
const videoFileInput = payload.copyCodecs
|
||||
? video.getWebTorrentFile(payload.resolution)
|
||||
? video.getWebVideoFile(payload.resolution)
|
||||
: video.getMaxQualityFile()
|
||||
|
||||
const videoOrStreamingPlaylist = videoFileInput.getVideoOrStreamingPlaylist()
|
||||
@@ -140,10 +140,10 @@ async function handleHLSJob (job: Job, payload: HLSTranscodingPayload, videoArg:
|
||||
|
||||
logger.info('HLS transcoding job for %s ended.', video.uuid, lTags(video.uuid), { payload })
|
||||
|
||||
if (payload.deleteWebTorrentFiles === true) {
|
||||
logger.info('Removing WebTorrent files of %s now we have a HLS version of it.', video.uuid, lTags(video.uuid))
|
||||
if (payload.deleteWebVideoFiles === true) {
|
||||
logger.info('Removing Web Video files of %s now we have a HLS version of it.', video.uuid, lTags(video.uuid))
|
||||
|
||||
await removeAllWebTorrentFiles(video)
|
||||
await removeAllWebVideoFiles(video)
|
||||
}
|
||||
|
||||
await onTranscodingEnded({ isNewVideo: payload.isNewVideo, moveVideoToNextState: true, video })
|
||||
|
||||
@@ -9,12 +9,12 @@ function generateHLSObjectBaseStorageKey (playlist: MStreamingPlaylistVideo) {
|
||||
return join(playlist.getStringType(), playlist.Video.uuid)
|
||||
}
|
||||
|
||||
function generateWebTorrentObjectStorageKey (filename: string) {
|
||||
function generateWebVideoObjectStorageKey (filename: string) {
|
||||
return filename
|
||||
}
|
||||
|
||||
export {
|
||||
generateHLSObjectStorageKey,
|
||||
generateHLSObjectBaseStorageKey,
|
||||
generateWebTorrentObjectStorageKey
|
||||
generateWebVideoObjectStorageKey
|
||||
}
|
||||
|
||||
@@ -2,9 +2,9 @@ import { GetObjectCommand } from '@aws-sdk/client-s3'
|
||||
import { getSignedUrl } from '@aws-sdk/s3-request-presigner'
|
||||
import { CONFIG } from '@server/initializers/config'
|
||||
import { MStreamingPlaylistVideo, MVideoFile } from '@server/types/models'
|
||||
import { generateHLSObjectStorageKey, generateWebTorrentObjectStorageKey } from './keys'
|
||||
import { generateHLSObjectStorageKey, generateWebVideoObjectStorageKey } from './keys'
|
||||
import { buildKey, getClient } from './shared'
|
||||
import { getHLSPublicFileUrl, getWebTorrentPublicFileUrl } from './urls'
|
||||
import { getHLSPublicFileUrl, getWebVideoPublicFileUrl } from './urls'
|
||||
|
||||
export async function generateWebVideoPresignedUrl (options: {
|
||||
file: MVideoFile
|
||||
@@ -12,7 +12,7 @@ export async function generateWebVideoPresignedUrl (options: {
|
||||
}) {
|
||||
const { file, downloadFilename } = options
|
||||
|
||||
const key = generateWebTorrentObjectStorageKey(file.filename)
|
||||
const key = generateWebVideoObjectStorageKey(file.filename)
|
||||
|
||||
const command = new GetObjectCommand({
|
||||
Bucket: CONFIG.OBJECT_STORAGE.VIDEOS.BUCKET_NAME,
|
||||
@@ -22,7 +22,7 @@ export async function generateWebVideoPresignedUrl (options: {
|
||||
|
||||
const url = await getSignedUrl(getClient(), command, { expiresIn: 3600 * 24 })
|
||||
|
||||
return getWebTorrentPublicFileUrl(url)
|
||||
return getWebVideoPublicFileUrl(url)
|
||||
}
|
||||
|
||||
export async function generateHLSFilePresignedUrl (options: {
|
||||
|
||||
@@ -7,19 +7,19 @@ import { StreamReplacer } from '@server/helpers/stream-replacer'
|
||||
import { MStreamingPlaylist, MVideo } from '@server/types/models'
|
||||
import { HttpStatusCode } from '@shared/models'
|
||||
import { injectQueryToPlaylistUrls } from '../hls'
|
||||
import { getHLSFileReadStream, getWebTorrentFileReadStream } from './videos'
|
||||
import { getHLSFileReadStream, getWebVideoFileReadStream } from './videos'
|
||||
|
||||
export async function proxifyWebTorrentFile (options: {
|
||||
export async function proxifyWebVideoFile (options: {
|
||||
req: express.Request
|
||||
res: express.Response
|
||||
filename: string
|
||||
}) {
|
||||
const { req, res, filename } = options
|
||||
|
||||
logger.debug('Proxifying WebTorrent file %s from object storage.', filename)
|
||||
logger.debug('Proxifying Web Video file %s from object storage.', filename)
|
||||
|
||||
try {
|
||||
const { response: s3Response, stream } = await getWebTorrentFileReadStream({
|
||||
const { response: s3Response, stream } = await getWebVideoFileReadStream({
|
||||
filename,
|
||||
rangeHeader: req.header('range')
|
||||
})
|
||||
|
||||
@@ -9,7 +9,7 @@ function getInternalUrl (config: BucketInfo, keyWithoutPrefix: string) {
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
function getWebTorrentPublicFileUrl (fileUrl: string) {
|
||||
function getWebVideoPublicFileUrl (fileUrl: string) {
|
||||
const baseUrl = CONFIG.OBJECT_STORAGE.VIDEOS.BASE_URL
|
||||
if (!baseUrl) return fileUrl
|
||||
|
||||
@@ -29,7 +29,7 @@ function getHLSPrivateFileUrl (video: MVideoUUID, filename: string) {
|
||||
return WEBSERVER.URL + OBJECT_STORAGE_PROXY_PATHS.STREAMING_PLAYLISTS.PRIVATE_HLS + video.uuid + `/${filename}`
|
||||
}
|
||||
|
||||
function getWebTorrentPrivateFileUrl (filename: string) {
|
||||
function getWebVideoPrivateFileUrl (filename: string) {
|
||||
return WEBSERVER.URL + OBJECT_STORAGE_PROXY_PATHS.PRIVATE_WEBSEED + filename
|
||||
}
|
||||
|
||||
@@ -38,11 +38,11 @@ function getWebTorrentPrivateFileUrl (filename: string) {
|
||||
export {
|
||||
getInternalUrl,
|
||||
|
||||
getWebTorrentPublicFileUrl,
|
||||
getWebVideoPublicFileUrl,
|
||||
getHLSPublicFileUrl,
|
||||
|
||||
getHLSPrivateFileUrl,
|
||||
getWebTorrentPrivateFileUrl,
|
||||
getWebVideoPrivateFileUrl,
|
||||
|
||||
replaceByBaseUrl
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ import { CONFIG } from '@server/initializers/config'
|
||||
import { MStreamingPlaylistVideo, MVideo, MVideoFile } from '@server/types/models'
|
||||
import { getHLSDirectory } from '../paths'
|
||||
import { VideoPathManager } from '../video-path-manager'
|
||||
import { generateHLSObjectBaseStorageKey, generateHLSObjectStorageKey, generateWebTorrentObjectStorageKey } from './keys'
|
||||
import { generateHLSObjectBaseStorageKey, generateHLSObjectStorageKey, generateWebVideoObjectStorageKey } from './keys'
|
||||
import {
|
||||
createObjectReadStream,
|
||||
listKeysOfPrefix,
|
||||
@@ -55,10 +55,10 @@ function storeHLSFileFromContent (playlist: MStreamingPlaylistVideo, path: strin
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
function storeWebTorrentFile (video: MVideo, file: MVideoFile) {
|
||||
function storeWebVideoFile (video: MVideo, file: MVideoFile) {
|
||||
return storeObject({
|
||||
inputPath: VideoPathManager.Instance.getFSVideoFileOutputPath(video, file),
|
||||
objectStorageKey: generateWebTorrentObjectStorageKey(file.filename),
|
||||
objectStorageKey: generateWebVideoObjectStorageKey(file.filename),
|
||||
bucketInfo: CONFIG.OBJECT_STORAGE.VIDEOS,
|
||||
isPrivate: video.hasPrivateStaticPath()
|
||||
})
|
||||
@@ -66,9 +66,9 @@ function storeWebTorrentFile (video: MVideo, file: MVideoFile) {
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
async function updateWebTorrentFileACL (video: MVideo, file: MVideoFile) {
|
||||
async function updateWebVideoFileACL (video: MVideo, file: MVideoFile) {
|
||||
await updateObjectACL({
|
||||
objectStorageKey: generateWebTorrentObjectStorageKey(file.filename),
|
||||
objectStorageKey: generateWebVideoObjectStorageKey(file.filename),
|
||||
bucketInfo: CONFIG.OBJECT_STORAGE.VIDEOS,
|
||||
isPrivate: video.hasPrivateStaticPath()
|
||||
})
|
||||
@@ -102,8 +102,8 @@ function removeHLSFileObjectStorageByFullKey (key: string) {
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
function removeWebTorrentObjectStorage (videoFile: MVideoFile) {
|
||||
return removeObject(generateWebTorrentObjectStorageKey(videoFile.filename), CONFIG.OBJECT_STORAGE.VIDEOS)
|
||||
function removeWebVideoObjectStorage (videoFile: MVideoFile) {
|
||||
return removeObject(generateWebVideoObjectStorageKey(videoFile.filename), CONFIG.OBJECT_STORAGE.VIDEOS)
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
@@ -122,10 +122,10 @@ async function makeHLSFileAvailable (playlist: MStreamingPlaylistVideo, filename
|
||||
return destination
|
||||
}
|
||||
|
||||
async function makeWebTorrentFileAvailable (filename: string, destination: string) {
|
||||
const key = generateWebTorrentObjectStorageKey(filename)
|
||||
async function makeWebVideoFileAvailable (filename: string, destination: string) {
|
||||
const key = generateWebVideoObjectStorageKey(filename)
|
||||
|
||||
logger.info('Fetching WebTorrent file %s from object storage to %s.', key, destination, lTags())
|
||||
logger.info('Fetching Web Video file %s from object storage to %s.', key, destination, lTags())
|
||||
|
||||
await makeAvailable({
|
||||
key,
|
||||
@@ -138,13 +138,13 @@ async function makeWebTorrentFileAvailable (filename: string, destination: strin
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
function getWebTorrentFileReadStream (options: {
|
||||
function getWebVideoFileReadStream (options: {
|
||||
filename: string
|
||||
rangeHeader: string
|
||||
}) {
|
||||
const { filename, rangeHeader } = options
|
||||
|
||||
const key = generateWebTorrentObjectStorageKey(filename)
|
||||
const key = generateWebVideoObjectStorageKey(filename)
|
||||
|
||||
return createObjectReadStream({
|
||||
key,
|
||||
@@ -174,12 +174,12 @@ function getHLSFileReadStream (options: {
|
||||
export {
|
||||
listHLSFileKeysOf,
|
||||
|
||||
storeWebTorrentFile,
|
||||
storeWebVideoFile,
|
||||
storeHLSFileFromFilename,
|
||||
storeHLSFileFromPath,
|
||||
storeHLSFileFromContent,
|
||||
|
||||
updateWebTorrentFileACL,
|
||||
updateWebVideoFileACL,
|
||||
updateHLSFilesACL,
|
||||
|
||||
removeHLSObjectStorage,
|
||||
@@ -187,11 +187,11 @@ export {
|
||||
removeHLSFileObjectStorageByPath,
|
||||
removeHLSFileObjectStorageByFullKey,
|
||||
|
||||
removeWebTorrentObjectStorage,
|
||||
removeWebVideoObjectStorage,
|
||||
|
||||
makeWebTorrentFileAvailable,
|
||||
makeWebVideoFileAvailable,
|
||||
makeHLSFileAvailable,
|
||||
|
||||
getWebTorrentFileReadStream,
|
||||
getWebVideoFileReadStream,
|
||||
getHLSFileReadStream
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ import { isVideoInPrivateDirectory } from './video-privacy'
|
||||
|
||||
// ################## Video file name ##################
|
||||
|
||||
function generateWebTorrentVideoFilename (resolution: number, extname: string) {
|
||||
function generateWebVideoFilename (resolution: number, extname: string) {
|
||||
return buildUUID() + '-' + resolution + extname
|
||||
}
|
||||
|
||||
@@ -76,7 +76,7 @@ function getFSTorrentFilePath (videoFile: MVideoFile) {
|
||||
|
||||
export {
|
||||
generateHLSVideoFilename,
|
||||
generateWebTorrentVideoFilename,
|
||||
generateWebVideoFilename,
|
||||
|
||||
generateTorrentFileName,
|
||||
getFSTorrentFilePath,
|
||||
|
||||
@@ -104,7 +104,7 @@ function buildVideosHelpers () {
|
||||
const video = await VideoModel.loadFull(id)
|
||||
if (!video) return undefined
|
||||
|
||||
const webtorrentVideoFiles = (video.VideoFiles || []).map(f => ({
|
||||
const webVideoFiles = (video.VideoFiles || []).map(f => ({
|
||||
path: f.storage === VideoStorage.FILE_SYSTEM
|
||||
? VideoPathManager.Instance.getFSVideoFileOutputPath(video, f)
|
||||
: null,
|
||||
@@ -138,8 +138,12 @@ function buildVideosHelpers () {
|
||||
}))
|
||||
|
||||
return {
|
||||
webtorrent: {
|
||||
videoFiles: webtorrentVideoFiles
|
||||
webtorrent: { // TODO: remove in v7
|
||||
videoFiles: webVideoFiles
|
||||
},
|
||||
|
||||
webVideo: {
|
||||
videoFiles: webVideoFiles
|
||||
},
|
||||
|
||||
hls: {
|
||||
|
||||
@@ -2,7 +2,7 @@ import { move } from 'fs-extra'
|
||||
import { dirname, join } from 'path'
|
||||
import { logger, LoggerTagsFn } from '@server/helpers/logger'
|
||||
import { onTranscodingEnded } from '@server/lib/transcoding/ended-transcoding'
|
||||
import { onWebTorrentVideoFileTranscoding } from '@server/lib/transcoding/web-transcoding'
|
||||
import { onWebVideoFileTranscoding } from '@server/lib/transcoding/web-transcoding'
|
||||
import { buildNewFile } from '@server/lib/video-file'
|
||||
import { VideoModel } from '@server/models/video/video'
|
||||
import { MVideoFullLight } from '@server/types/models'
|
||||
@@ -22,7 +22,7 @@ export async function onVODWebVideoOrAudioMergeTranscodingJob (options: {
|
||||
const newVideoFilePath = join(dirname(videoFilePath), videoFile.filename)
|
||||
await move(videoFilePath, newVideoFilePath)
|
||||
|
||||
await onWebTorrentVideoFileTranscoding({
|
||||
await onWebVideoFileTranscoding({
|
||||
video,
|
||||
videoFile,
|
||||
videoOutputPath: newVideoFilePath
|
||||
|
||||
@@ -83,7 +83,7 @@ export class VODAudioMergeTranscodingJobHandler extends AbstractVODTranscodingJo
|
||||
|
||||
// We can remove the old audio file
|
||||
const oldAudioFile = video.VideoFiles[0]
|
||||
await video.removeWebTorrentFile(oldAudioFile)
|
||||
await video.removeWebVideoFile(oldAudioFile)
|
||||
await oldAudioFile.destroy()
|
||||
video.VideoFiles = []
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ import { renameVideoFileInPlaylist } from '@server/lib/hls'
|
||||
import { getHlsResolutionPlaylistFilename } from '@server/lib/paths'
|
||||
import { onTranscodingEnded } from '@server/lib/transcoding/ended-transcoding'
|
||||
import { onHLSVideoFileTranscoding } from '@server/lib/transcoding/hls-transcoding'
|
||||
import { buildNewFile, removeAllWebTorrentFiles } from '@server/lib/video-file'
|
||||
import { buildNewFile, removeAllWebVideoFiles } from '@server/lib/video-file'
|
||||
import { VideoJobInfoModel } from '@server/models/video/video-job-info'
|
||||
import { MVideo } from '@server/types/models'
|
||||
import { MRunnerJob } from '@server/types/models/runners'
|
||||
@@ -106,7 +106,7 @@ export class VODHLSTranscodingJobHandler extends AbstractVODTranscodingJobHandle
|
||||
if (privatePayload.deleteWebVideoFiles === true) {
|
||||
logger.info('Removing web video files of %s now we have a HLS version of it.', video.uuid, this.lTags(video.uuid))
|
||||
|
||||
await removeAllWebTorrentFiles(video)
|
||||
await removeAllWebVideoFiles(video)
|
||||
}
|
||||
|
||||
logger.info('Runner VOD HLS job %s for %s ended.', runnerJob.uuid, video.uuid, this.lTags(runnerJob.uuid, video.uuid))
|
||||
|
||||
@@ -23,7 +23,7 @@ import { getLocalVideoCacheFileActivityPubUrl, getLocalVideoCacheStreamingPlayli
|
||||
import { getOrCreateAPVideo } from '../activitypub/videos'
|
||||
import { downloadPlaylistSegments } from '../hls'
|
||||
import { removeVideoRedundancy } from '../redundancy'
|
||||
import { generateHLSRedundancyUrl, generateWebTorrentRedundancyUrl } from '../video-urls'
|
||||
import { generateHLSRedundancyUrl, generateWebVideoRedundancyUrl } from '../video-urls'
|
||||
import { AbstractScheduler } from './abstract-scheduler'
|
||||
|
||||
const lTags = loggerTagsFactory('redundancy')
|
||||
@@ -244,7 +244,7 @@ export class VideosRedundancyScheduler extends AbstractScheduler {
|
||||
const createdModel: MVideoRedundancyFileVideo = await VideoRedundancyModel.create({
|
||||
expiresOn,
|
||||
url: getLocalVideoCacheFileActivityPubUrl(file),
|
||||
fileUrl: generateWebTorrentRedundancyUrl(file),
|
||||
fileUrl: generateWebVideoRedundancyUrl(file),
|
||||
strategy,
|
||||
videoFileId: file.id,
|
||||
actorId: serverActor.id
|
||||
|
||||
@@ -15,7 +15,7 @@ export function createOptimizeOrMergeAudioJobs (options: {
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
export function createTranscodingJobs (options: {
|
||||
transcodingType: 'hls' | 'webtorrent'
|
||||
transcodingType: 'hls' | 'webtorrent' | 'web-video' // TODO: remove webtorrent in v7
|
||||
video: MVideoFullLight
|
||||
resolutions: number[]
|
||||
isNewVideo: boolean
|
||||
|
||||
@@ -12,7 +12,7 @@ export abstract class AbstractJobBuilder {
|
||||
}): Promise<any>
|
||||
|
||||
abstract createTranscodingJobs (options: {
|
||||
transcodingType: 'hls' | 'webtorrent'
|
||||
transcodingType: 'hls' | 'webtorrent' | 'web-video' // TODO: remove webtorrent in v7
|
||||
video: MVideoFullLight
|
||||
resolutions: number[]
|
||||
isNewVideo: boolean
|
||||
|
||||
@@ -12,7 +12,7 @@ import { ffprobePromise, getVideoStreamDimensionsInfo, getVideoStreamFPS, hasAud
|
||||
import {
|
||||
HLSTranscodingPayload,
|
||||
MergeAudioTranscodingPayload,
|
||||
NewWebTorrentResolutionTranscodingPayload,
|
||||
NewWebVideoResolutionTranscodingPayload,
|
||||
OptimizeTranscodingPayload,
|
||||
VideoTranscodingPayload
|
||||
} from '@shared/models'
|
||||
@@ -33,7 +33,7 @@ export class TranscodingJobQueueBuilder extends AbstractJobBuilder {
|
||||
const { video, videoFile, isNewVideo, user, videoFileAlreadyLocked } = options
|
||||
|
||||
let mergeOrOptimizePayload: MergeAudioTranscodingPayload | OptimizeTranscodingPayload
|
||||
let nextTranscodingSequentialJobPayloads: (NewWebTorrentResolutionTranscodingPayload | HLSTranscodingPayload)[][] = []
|
||||
let nextTranscodingSequentialJobPayloads: (NewWebVideoResolutionTranscodingPayload | HLSTranscodingPayload)[][] = []
|
||||
|
||||
const mutexReleaser = videoFileAlreadyLocked
|
||||
? () => {}
|
||||
@@ -60,7 +60,7 @@ export class TranscodingJobQueueBuilder extends AbstractJobBuilder {
|
||||
if (CONFIG.TRANSCODING.HLS.ENABLED === true) {
|
||||
nextTranscodingSequentialJobPayloads.push([
|
||||
this.buildHLSJobPayload({
|
||||
deleteWebTorrentFiles: CONFIG.TRANSCODING.WEBTORRENT.ENABLED === false,
|
||||
deleteWebVideoFiles: CONFIG.TRANSCODING.WEBTORRENT.ENABLED === false,
|
||||
|
||||
// We had some issues with a web video quick transcoded while producing a HLS version of it
|
||||
copyCodecs: !quickTranscode,
|
||||
@@ -116,7 +116,7 @@ export class TranscodingJobQueueBuilder extends AbstractJobBuilder {
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
async createTranscodingJobs (options: {
|
||||
transcodingType: 'hls' | 'webtorrent'
|
||||
transcodingType: 'hls' | 'webtorrent' | 'web-video' // TODO: remove webtorrent in v7
|
||||
video: MVideoFullLight
|
||||
resolutions: number[]
|
||||
isNewVideo: boolean
|
||||
@@ -138,8 +138,8 @@ export class TranscodingJobQueueBuilder extends AbstractJobBuilder {
|
||||
return this.buildHLSJobPayload({ videoUUID: video.uuid, resolution, fps, isNewVideo })
|
||||
}
|
||||
|
||||
if (transcodingType === 'webtorrent') {
|
||||
return this.buildWebTorrentJobPayload({ videoUUID: video.uuid, resolution, fps, isNewVideo })
|
||||
if (transcodingType === 'webtorrent' || transcodingType === 'web-video') {
|
||||
return this.buildWebVideoJobPayload({ videoUUID: video.uuid, resolution, fps, isNewVideo })
|
||||
}
|
||||
|
||||
throw new Error('Unknown transcoding type')
|
||||
@@ -149,7 +149,7 @@ export class TranscodingJobQueueBuilder extends AbstractJobBuilder {
|
||||
|
||||
const parent = transcodingType === 'hls'
|
||||
? this.buildHLSJobPayload({ videoUUID: video.uuid, resolution: maxResolution, fps, isNewVideo })
|
||||
: this.buildWebTorrentJobPayload({ videoUUID: video.uuid, resolution: maxResolution, fps, isNewVideo })
|
||||
: this.buildWebVideoJobPayload({ videoUUID: video.uuid, resolution: maxResolution, fps, isNewVideo })
|
||||
|
||||
// Process the last resolution after the other ones to prevent concurrency issue
|
||||
// Because low resolutions use the biggest one as ffmpeg input
|
||||
@@ -160,8 +160,8 @@ export class TranscodingJobQueueBuilder extends AbstractJobBuilder {
|
||||
|
||||
private async createTranscodingJobsWithChildren (options: {
|
||||
videoUUID: string
|
||||
parent: (HLSTranscodingPayload | NewWebTorrentResolutionTranscodingPayload)
|
||||
children: (HLSTranscodingPayload | NewWebTorrentResolutionTranscodingPayload)[]
|
||||
parent: (HLSTranscodingPayload | NewWebVideoResolutionTranscodingPayload)
|
||||
children: (HLSTranscodingPayload | NewWebVideoResolutionTranscodingPayload)[]
|
||||
user: MUserId | null
|
||||
}) {
|
||||
const { videoUUID, parent, children, user } = options
|
||||
@@ -203,14 +203,14 @@ export class TranscodingJobQueueBuilder extends AbstractJobBuilder {
|
||||
options
|
||||
)
|
||||
|
||||
const sequentialPayloads: (NewWebTorrentResolutionTranscodingPayload | HLSTranscodingPayload)[][] = []
|
||||
const sequentialPayloads: (NewWebVideoResolutionTranscodingPayload | HLSTranscodingPayload)[][] = []
|
||||
|
||||
for (const resolution of resolutionsEnabled) {
|
||||
const fps = computeOutputFPS({ inputFPS: inputVideoFPS, resolution })
|
||||
|
||||
if (CONFIG.TRANSCODING.WEBTORRENT.ENABLED) {
|
||||
const payloads: (NewWebTorrentResolutionTranscodingPayload | HLSTranscodingPayload)[] = [
|
||||
this.buildWebTorrentJobPayload({
|
||||
const payloads: (NewWebVideoResolutionTranscodingPayload | HLSTranscodingPayload)[] = [
|
||||
this.buildWebVideoJobPayload({
|
||||
videoUUID: video.uuid,
|
||||
resolution,
|
||||
fps,
|
||||
@@ -253,10 +253,10 @@ export class TranscodingJobQueueBuilder extends AbstractJobBuilder {
|
||||
resolution: number
|
||||
fps: number
|
||||
isNewVideo: boolean
|
||||
deleteWebTorrentFiles?: boolean // default false
|
||||
deleteWebVideoFiles?: boolean // default false
|
||||
copyCodecs?: boolean // default false
|
||||
}): HLSTranscodingPayload {
|
||||
const { videoUUID, resolution, fps, isNewVideo, deleteWebTorrentFiles = false, copyCodecs = false } = options
|
||||
const { videoUUID, resolution, fps, isNewVideo, deleteWebVideoFiles = false, copyCodecs = false } = options
|
||||
|
||||
return {
|
||||
type: 'new-resolution-to-hls',
|
||||
@@ -265,20 +265,20 @@ export class TranscodingJobQueueBuilder extends AbstractJobBuilder {
|
||||
fps,
|
||||
copyCodecs,
|
||||
isNewVideo,
|
||||
deleteWebTorrentFiles
|
||||
deleteWebVideoFiles
|
||||
}
|
||||
}
|
||||
|
||||
private buildWebTorrentJobPayload (options: {
|
||||
private buildWebVideoJobPayload (options: {
|
||||
videoUUID: string
|
||||
resolution: number
|
||||
fps: number
|
||||
isNewVideo: boolean
|
||||
}): NewWebTorrentResolutionTranscodingPayload {
|
||||
}): NewWebVideoResolutionTranscodingPayload {
|
||||
const { videoUUID, resolution, fps, isNewVideo } = options
|
||||
|
||||
return {
|
||||
type: 'new-resolution-to-webtorrent',
|
||||
type: 'new-resolution-to-web-video',
|
||||
videoUUID,
|
||||
isNewVideo,
|
||||
resolution,
|
||||
@@ -294,7 +294,7 @@ export class TranscodingJobQueueBuilder extends AbstractJobBuilder {
|
||||
const { videoUUID, isNewVideo, hasChildren } = options
|
||||
|
||||
return {
|
||||
type: 'merge-audio-to-webtorrent',
|
||||
type: 'merge-audio-to-web-video',
|
||||
resolution: DEFAULT_AUDIO_RESOLUTION,
|
||||
fps: VIDEO_TRANSCODING_FPS.AUDIO_MERGE,
|
||||
videoUUID,
|
||||
@@ -312,7 +312,7 @@ export class TranscodingJobQueueBuilder extends AbstractJobBuilder {
|
||||
const { videoUUID, quickTranscode, isNewVideo, hasChildren } = options
|
||||
|
||||
return {
|
||||
type: 'optimize-to-webtorrent',
|
||||
type: 'optimize-to-web-video',
|
||||
videoUUID,
|
||||
isNewVideo,
|
||||
hasChildren,
|
||||
|
||||
@@ -89,7 +89,7 @@ export class TranscodingRunnerJobBuilder extends AbstractJobBuilder {
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
async createTranscodingJobs (options: {
|
||||
transcodingType: 'hls' | 'webtorrent'
|
||||
transcodingType: 'hls' | 'webtorrent' | 'web-video' // TODO: remove webtorrent in v7
|
||||
video: MVideoFullLight
|
||||
resolutions: number[]
|
||||
isNewVideo: boolean
|
||||
@@ -130,7 +130,7 @@ export class TranscodingRunnerJobBuilder extends AbstractJobBuilder {
|
||||
continue
|
||||
}
|
||||
|
||||
if (transcodingType === 'webtorrent') {
|
||||
if (transcodingType === 'webtorrent' || transcodingType === 'web-video') {
|
||||
await new VODWebVideoTranscodingJobHandler().create({
|
||||
video,
|
||||
resolution,
|
||||
|
||||
@@ -10,7 +10,7 @@ import { VideoResolution, VideoStorage } from '@shared/models'
|
||||
import { CONFIG } from '../../initializers/config'
|
||||
import { VideoFileModel } from '../../models/video/video-file'
|
||||
import { JobQueue } from '../job-queue'
|
||||
import { generateWebTorrentVideoFilename } from '../paths'
|
||||
import { generateWebVideoFilename } from '../paths'
|
||||
import { buildFileMetadata } from '../video-file'
|
||||
import { VideoPathManager } from '../video-path-manager'
|
||||
import { buildFFmpegVOD } from './shared'
|
||||
@@ -63,10 +63,10 @@ export async function optimizeOriginalVideofile (options: {
|
||||
// Important to do this before getVideoFilename() to take in account the new filename
|
||||
inputVideoFile.resolution = resolution
|
||||
inputVideoFile.extname = newExtname
|
||||
inputVideoFile.filename = generateWebTorrentVideoFilename(resolution, newExtname)
|
||||
inputVideoFile.filename = generateWebVideoFilename(resolution, newExtname)
|
||||
inputVideoFile.storage = VideoStorage.FILE_SYSTEM
|
||||
|
||||
const { videoFile } = await onWebTorrentVideoFileTranscoding({
|
||||
const { videoFile } = await onWebVideoFileTranscoding({
|
||||
video,
|
||||
videoFile: inputVideoFile,
|
||||
videoOutputPath
|
||||
@@ -83,8 +83,8 @@ export async function optimizeOriginalVideofile (options: {
|
||||
}
|
||||
}
|
||||
|
||||
// Transcode the original video file to a lower resolution compatible with WebTorrent
|
||||
export async function transcodeNewWebTorrentResolution (options: {
|
||||
// Transcode the original video file to a lower resolution compatible with web browsers
|
||||
export async function transcodeNewWebVideoResolution (options: {
|
||||
video: MVideoFullLight
|
||||
resolution: VideoResolution
|
||||
fps: number
|
||||
@@ -105,7 +105,7 @@ export async function transcodeNewWebTorrentResolution (options: {
|
||||
const newVideoFile = new VideoFileModel({
|
||||
resolution,
|
||||
extname: newExtname,
|
||||
filename: generateWebTorrentVideoFilename(resolution, newExtname),
|
||||
filename: generateWebVideoFilename(resolution, newExtname),
|
||||
size: 0,
|
||||
videoId: video.id
|
||||
})
|
||||
@@ -126,7 +126,7 @@ export async function transcodeNewWebTorrentResolution (options: {
|
||||
|
||||
await buildFFmpegVOD(job).transcode(transcodeOptions)
|
||||
|
||||
return onWebTorrentVideoFileTranscoding({ video, videoFile: newVideoFile, videoOutputPath })
|
||||
return onWebVideoFileTranscoding({ video, videoFile: newVideoFile, videoOutputPath })
|
||||
})
|
||||
|
||||
return result
|
||||
@@ -189,14 +189,14 @@ export async function mergeAudioVideofile (options: {
|
||||
// Important to do this before getVideoFilename() to take in account the new file extension
|
||||
inputVideoFile.extname = newExtname
|
||||
inputVideoFile.resolution = resolution
|
||||
inputVideoFile.filename = generateWebTorrentVideoFilename(inputVideoFile.resolution, newExtname)
|
||||
inputVideoFile.filename = generateWebVideoFilename(inputVideoFile.resolution, newExtname)
|
||||
|
||||
// ffmpeg generated a new video file, so update the video duration
|
||||
// See https://trac.ffmpeg.org/ticket/5456
|
||||
video.duration = await getVideoStreamDuration(videoOutputPath)
|
||||
await video.save()
|
||||
|
||||
return onWebTorrentVideoFileTranscoding({
|
||||
return onWebVideoFileTranscoding({
|
||||
video,
|
||||
videoFile: inputVideoFile,
|
||||
videoOutputPath,
|
||||
@@ -210,7 +210,7 @@ export async function mergeAudioVideofile (options: {
|
||||
}
|
||||
}
|
||||
|
||||
export async function onWebTorrentVideoFileTranscoding (options: {
|
||||
export async function onWebVideoFileTranscoding (options: {
|
||||
video: MVideoFullLight
|
||||
videoFile: MVideoFile
|
||||
videoOutputPath: string
|
||||
@@ -239,8 +239,8 @@ export async function onWebTorrentVideoFileTranscoding (options: {
|
||||
|
||||
await createTorrentAndSetInfoHash(video, videoFile)
|
||||
|
||||
const oldFile = await VideoFileModel.loadWebTorrentFile({ videoId: video.id, fps: videoFile.fps, resolution: videoFile.resolution })
|
||||
if (oldFile) await video.removeWebTorrentFile(oldFile)
|
||||
const oldFile = await VideoFileModel.loadWebVideoFile({ videoId: video.id, fps: videoFile.fps, resolution: videoFile.resolution })
|
||||
if (oldFile) await video.removeWebVideoFile(oldFile)
|
||||
|
||||
await VideoFileModel.customUpsert(videoFile, 'video', undefined)
|
||||
video.VideoFiles = await video.$get('VideoFiles')
|
||||
|
||||
@@ -7,7 +7,7 @@ import { getFileSize } from '@shared/extra-utils'
|
||||
import { ffprobePromise, getVideoStreamDimensionsInfo, getVideoStreamFPS, isAudioFile } from '@shared/ffmpeg'
|
||||
import { VideoFileMetadata, VideoResolution } from '@shared/models'
|
||||
import { lTags } from './object-storage/shared'
|
||||
import { generateHLSVideoFilename, generateWebTorrentVideoFilename } from './paths'
|
||||
import { generateHLSVideoFilename, generateWebVideoFilename } from './paths'
|
||||
import { VideoPathManager } from './video-path-manager'
|
||||
|
||||
async function buildNewFile (options: {
|
||||
@@ -33,7 +33,7 @@ async function buildNewFile (options: {
|
||||
}
|
||||
|
||||
videoFile.filename = mode === 'web-video'
|
||||
? generateWebTorrentVideoFilename(videoFile.resolution, videoFile.extname)
|
||||
? generateWebVideoFilename(videoFile.resolution, videoFile.extname)
|
||||
: generateHLSVideoFilename(videoFile.resolution)
|
||||
|
||||
return videoFile
|
||||
@@ -85,12 +85,12 @@ async function removeHLSFile (video: MVideoWithAllFiles, fileToDeleteId: number)
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
async function removeAllWebTorrentFiles (video: MVideoWithAllFiles) {
|
||||
async function removeAllWebVideoFiles (video: MVideoWithAllFiles) {
|
||||
const videoFileMutexReleaser = await VideoPathManager.Instance.lockFiles(video.uuid)
|
||||
|
||||
try {
|
||||
for (const file of video.VideoFiles) {
|
||||
await video.removeWebTorrentFile(file)
|
||||
await video.removeWebVideoFile(file)
|
||||
await file.destroy()
|
||||
}
|
||||
|
||||
@@ -102,17 +102,17 @@ async function removeAllWebTorrentFiles (video: MVideoWithAllFiles) {
|
||||
return video
|
||||
}
|
||||
|
||||
async function removeWebTorrentFile (video: MVideoWithAllFiles, fileToDeleteId: number) {
|
||||
async function removeWebVideoFile (video: MVideoWithAllFiles, fileToDeleteId: number) {
|
||||
const files = video.VideoFiles
|
||||
|
||||
if (files.length === 1) {
|
||||
return removeAllWebTorrentFiles(video)
|
||||
return removeAllWebVideoFiles(video)
|
||||
}
|
||||
|
||||
const videoFileMutexReleaser = await VideoPathManager.Instance.lockFiles(video.uuid)
|
||||
try {
|
||||
const toDelete = files.find(f => f.id === fileToDeleteId)
|
||||
await video.removeWebTorrentFile(toDelete)
|
||||
await video.removeWebVideoFile(toDelete)
|
||||
await toDelete.destroy()
|
||||
|
||||
video.VideoFiles = files.filter(f => f.id !== toDelete.id)
|
||||
@@ -138,8 +138,8 @@ export {
|
||||
|
||||
removeHLSPlaylist,
|
||||
removeHLSFile,
|
||||
removeAllWebTorrentFiles,
|
||||
removeWebTorrentFile,
|
||||
removeAllWebVideoFiles,
|
||||
removeWebVideoFile,
|
||||
|
||||
buildFileMetadata
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ import { DIRECTORIES } from '@server/initializers/constants'
|
||||
import { MStreamingPlaylistVideo, MVideo, MVideoFile, MVideoFileStreamingPlaylistVideo, MVideoFileVideo } from '@server/types/models'
|
||||
import { buildUUID } from '@shared/extra-utils'
|
||||
import { VideoStorage } from '@shared/models'
|
||||
import { makeHLSFileAvailable, makeWebTorrentFileAvailable } from './object-storage'
|
||||
import { makeHLSFileAvailable, makeWebVideoFileAvailable } from './object-storage'
|
||||
import { getHLSDirectory, getHLSRedundancyDirectory, getHlsResolutionPlaylistFilename } from './paths'
|
||||
import { isVideoInPrivateDirectory } from './video-privacy'
|
||||
|
||||
@@ -78,7 +78,7 @@ class VideoPathManager {
|
||||
}
|
||||
|
||||
return this.makeAvailableFactory(
|
||||
() => makeWebTorrentFileAvailable(videoFile.filename, destination),
|
||||
() => makeWebVideoFileAvailable(videoFile.filename, destination),
|
||||
true,
|
||||
cb
|
||||
)
|
||||
|
||||
@@ -4,7 +4,7 @@ import { logger } from '@server/helpers/logger'
|
||||
import { DIRECTORIES } from '@server/initializers/constants'
|
||||
import { MVideo, MVideoFile, MVideoFullLight } from '@server/types/models'
|
||||
import { VideoPrivacy, VideoStorage } from '@shared/models'
|
||||
import { updateHLSFilesACL, updateWebTorrentFileACL } from './object-storage'
|
||||
import { updateHLSFilesACL, updateWebVideoFileACL } from './object-storage'
|
||||
|
||||
const validPrivacySet = new Set([
|
||||
VideoPrivacy.PRIVATE,
|
||||
@@ -67,9 +67,9 @@ async function moveFiles (options: {
|
||||
|
||||
for (const file of video.VideoFiles) {
|
||||
if (file.storage === VideoStorage.FILE_SYSTEM) {
|
||||
await moveWebTorrentFileOnFS(type, video, file)
|
||||
await moveWebVideoFileOnFS(type, video, file)
|
||||
} else {
|
||||
await updateWebTorrentFileACL(video, file)
|
||||
await updateWebVideoFileACL(video, file)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -84,22 +84,22 @@ async function moveFiles (options: {
|
||||
}
|
||||
}
|
||||
|
||||
async function moveWebTorrentFileOnFS (type: MoveType, video: MVideo, file: MVideoFile) {
|
||||
const directories = getWebTorrentDirectories(type)
|
||||
async function moveWebVideoFileOnFS (type: MoveType, video: MVideo, file: MVideoFile) {
|
||||
const directories = getWebVideoDirectories(type)
|
||||
|
||||
const source = join(directories.old, file.filename)
|
||||
const destination = join(directories.new, file.filename)
|
||||
|
||||
try {
|
||||
logger.info('Moving WebTorrent files of %s after privacy change (%s -> %s).', video.uuid, source, destination)
|
||||
logger.info('Moving web video files of %s after privacy change (%s -> %s).', video.uuid, source, destination)
|
||||
|
||||
await move(source, destination)
|
||||
} catch (err) {
|
||||
logger.error('Cannot move webtorrent file %s to %s after privacy change', source, destination, { err })
|
||||
logger.error('Cannot move web video file %s to %s after privacy change', source, destination, { err })
|
||||
}
|
||||
}
|
||||
|
||||
function getWebTorrentDirectories (moveType: MoveType) {
|
||||
function getWebVideoDirectories (moveType: MoveType) {
|
||||
if (moveType === 'private-to-public') {
|
||||
return { old: DIRECTORIES.VIDEOS.PRIVATE, new: DIRECTORIES.VIDEOS.PUBLIC }
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ import { JobQueue } from './job-queue'
|
||||
import { VideoStudioTranscodingJobHandler } from './runners'
|
||||
import { createOptimizeOrMergeAudioJobs } from './transcoding/create-transcoding-job'
|
||||
import { getTranscodingJobPriority } from './transcoding/transcoding-priority'
|
||||
import { buildNewFile, removeHLSPlaylist, removeWebTorrentFile } from './video-file'
|
||||
import { buildNewFile, removeHLSPlaylist, removeWebVideoFile } from './video-file'
|
||||
import { VideoPathManager } from './video-path-manager'
|
||||
|
||||
const lTags = loggerTagsFactory('video-studio')
|
||||
@@ -119,12 +119,12 @@ export async function onVideoStudioEnded (options: {
|
||||
// Private
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
async function removeAllFiles (video: MVideoWithAllFiles, webTorrentFileException: MVideoFile) {
|
||||
async function removeAllFiles (video: MVideoWithAllFiles, webVideoFileException: MVideoFile) {
|
||||
await removeHLSPlaylist(video)
|
||||
|
||||
for (const file of video.VideoFiles) {
|
||||
if (file.id === webTorrentFileException.id) continue
|
||||
if (file.id === webVideoFileException.id) continue
|
||||
|
||||
await removeWebTorrentFile(video, file.id)
|
||||
await removeWebVideoFile(video, file.id)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ function generateHLSRedundancyUrl (video: MVideo, playlist: MStreamingPlaylist)
|
||||
return WEBSERVER.URL + STATIC_PATHS.REDUNDANCY + playlist.getStringType() + '/' + video.uuid
|
||||
}
|
||||
|
||||
function generateWebTorrentRedundancyUrl (file: MVideoFile) {
|
||||
function generateWebVideoRedundancyUrl (file: MVideoFile) {
|
||||
return WEBSERVER.URL + STATIC_PATHS.REDUNDANCY + file.filename
|
||||
}
|
||||
|
||||
@@ -26,6 +26,6 @@ function getLocalVideoFileMetadataUrl (video: MVideoUUID, videoFile: MVideoFile)
|
||||
export {
|
||||
getLocalVideoFileMetadataUrl,
|
||||
|
||||
generateWebTorrentRedundancyUrl,
|
||||
generateWebVideoRedundancyUrl,
|
||||
generateHLSRedundancyUrl
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ const staticFileTokenBypass = new LRUCache<string, LRUValue>({
|
||||
ttl: LRU_CACHE.STATIC_VIDEO_FILES_RIGHTS_CHECK.TTL
|
||||
})
|
||||
|
||||
const ensureCanAccessVideoPrivateWebTorrentFiles = [
|
||||
const ensureCanAccessVideoPrivateWebVideoFiles = [
|
||||
query('videoFileToken').optional().custom(exists),
|
||||
|
||||
isValidVideoPasswordHeader(),
|
||||
@@ -48,7 +48,7 @@ const ensureCanAccessVideoPrivateWebTorrentFiles = [
|
||||
return res.sendStatus(HttpStatusCode.FORBIDDEN_403)
|
||||
}
|
||||
|
||||
const result = await isWebTorrentAllowed(req, res)
|
||||
const result = await isWebVideoAllowed(req, res)
|
||||
|
||||
staticFileTokenBypass.set(cacheKey, result)
|
||||
|
||||
@@ -122,13 +122,13 @@ const ensureCanAccessPrivateVideoHLSFiles = [
|
||||
]
|
||||
|
||||
export {
|
||||
ensureCanAccessVideoPrivateWebTorrentFiles,
|
||||
ensureCanAccessVideoPrivateWebVideoFiles,
|
||||
ensureCanAccessPrivateVideoHLSFiles
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
async function isWebTorrentAllowed (req: express.Request, res: express.Response) {
|
||||
async function isWebVideoAllowed (req: express.Request, res: express.Response) {
|
||||
const filename = basename(req.path)
|
||||
|
||||
const file = await VideoFileModel.loadWithVideoByFilename(filename)
|
||||
|
||||
@@ -5,7 +5,7 @@ import { MVideo } from '@server/types/models'
|
||||
import { HttpStatusCode } from '@shared/models'
|
||||
import { areValidationErrors, doesVideoExist, isValidVideoIdParam } from '../shared'
|
||||
|
||||
const videoFilesDeleteWebTorrentValidator = [
|
||||
const videoFilesDeleteWebVideoValidator = [
|
||||
isValidVideoIdParam('id'),
|
||||
|
||||
async (req: express.Request, res: express.Response, next: express.NextFunction) => {
|
||||
@@ -16,17 +16,17 @@ const videoFilesDeleteWebTorrentValidator = [
|
||||
|
||||
if (!checkLocalVideo(video, res)) return
|
||||
|
||||
if (!video.hasWebTorrentFiles()) {
|
||||
if (!video.hasWebVideoFiles()) {
|
||||
return res.fail({
|
||||
status: HttpStatusCode.BAD_REQUEST_400,
|
||||
message: 'This video does not have WebTorrent files'
|
||||
message: 'This video does not have Web Video files'
|
||||
})
|
||||
}
|
||||
|
||||
if (!video.getHLSPlaylist()) {
|
||||
return res.fail({
|
||||
status: HttpStatusCode.BAD_REQUEST_400,
|
||||
message: 'Cannot delete WebTorrent files since this video does not have HLS playlist'
|
||||
message: 'Cannot delete Web Video files since this video does not have HLS playlist'
|
||||
})
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@ const videoFilesDeleteWebTorrentValidator = [
|
||||
}
|
||||
]
|
||||
|
||||
const videoFilesDeleteWebTorrentFileValidator = [
|
||||
const videoFilesDeleteWebVideoFileValidator = [
|
||||
isValidVideoIdParam('id'),
|
||||
|
||||
param('videoFileId')
|
||||
@@ -52,14 +52,14 @@ const videoFilesDeleteWebTorrentFileValidator = [
|
||||
if (!files.find(f => f.id === +req.params.videoFileId)) {
|
||||
return res.fail({
|
||||
status: HttpStatusCode.NOT_FOUND_404,
|
||||
message: 'This video does not have this WebTorrent file id'
|
||||
message: 'This video does not have this Web Video file id'
|
||||
})
|
||||
}
|
||||
|
||||
if (files.length === 1 && !video.getHLSPlaylist()) {
|
||||
return res.fail({
|
||||
status: HttpStatusCode.BAD_REQUEST_400,
|
||||
message: 'Cannot delete WebTorrent files since this video does not have HLS playlist'
|
||||
message: 'Cannot delete Web Video files since this video does not have HLS playlist'
|
||||
})
|
||||
}
|
||||
|
||||
@@ -87,10 +87,10 @@ const videoFilesDeleteHLSValidator = [
|
||||
})
|
||||
}
|
||||
|
||||
if (!video.hasWebTorrentFiles()) {
|
||||
if (!video.hasWebVideoFiles()) {
|
||||
return res.fail({
|
||||
status: HttpStatusCode.BAD_REQUEST_400,
|
||||
message: 'Cannot delete HLS playlist since this video does not have WebTorrent files'
|
||||
message: 'Cannot delete HLS playlist since this video does not have Web Video files'
|
||||
})
|
||||
}
|
||||
|
||||
@@ -128,10 +128,10 @@ const videoFilesDeleteHLSFileValidator = [
|
||||
}
|
||||
|
||||
// Last file to delete
|
||||
if (hlsFiles.length === 1 && !video.hasWebTorrentFiles()) {
|
||||
if (hlsFiles.length === 1 && !video.hasWebVideoFiles()) {
|
||||
return res.fail({
|
||||
status: HttpStatusCode.BAD_REQUEST_400,
|
||||
message: 'Cannot delete last HLS playlist file since this video does not have WebTorrent files'
|
||||
message: 'Cannot delete last HLS playlist file since this video does not have Web Video files'
|
||||
})
|
||||
}
|
||||
|
||||
@@ -140,8 +140,8 @@ const videoFilesDeleteHLSFileValidator = [
|
||||
]
|
||||
|
||||
export {
|
||||
videoFilesDeleteWebTorrentValidator,
|
||||
videoFilesDeleteWebTorrentFileValidator,
|
||||
videoFilesDeleteWebVideoValidator,
|
||||
videoFilesDeleteWebVideoFileValidator,
|
||||
|
||||
videoFilesDeleteHLSValidator,
|
||||
videoFilesDeleteHLSFileValidator
|
||||
|
||||
@@ -506,10 +506,14 @@ const commonVideosFiltersValidator = [
|
||||
.optional()
|
||||
.customSanitizer(toBooleanOrNull)
|
||||
.custom(isBooleanValid).withMessage('Should have a valid hasHLSFiles boolean'),
|
||||
query('hasWebtorrentFiles')
|
||||
query('hasWebtorrentFiles') // TODO: remove in v7
|
||||
.optional()
|
||||
.customSanitizer(toBooleanOrNull)
|
||||
.custom(isBooleanValid).withMessage('Should have a valid hasWebtorrentFiles boolean'),
|
||||
query('hasWebVideoFiles')
|
||||
.optional()
|
||||
.customSanitizer(toBooleanOrNull)
|
||||
.custom(isBooleanValid).withMessage('Should have a valid hasWebVideoFiles boolean'),
|
||||
query('skipCount')
|
||||
.optional()
|
||||
.customSanitizer(toBooleanOrNull)
|
||||
|
||||
@@ -162,7 +162,7 @@ export class VideoRedundancyModel extends Model<Partial<AttributesOnly<VideoRedu
|
||||
const logIdentifier = `${videoFile.Video.uuid}-${videoFile.resolution}`
|
||||
logger.info('Removing duplicated video file %s.', logIdentifier)
|
||||
|
||||
videoFile.Video.removeWebTorrentFile(videoFile, true)
|
||||
videoFile.Video.removeWebVideoFile(videoFile, true)
|
||||
.catch(err => logger.error('Cannot delete %s files.', logIdentifier, { err }))
|
||||
}
|
||||
|
||||
|
||||
@@ -786,7 +786,7 @@ export class UserModel extends Model<Partial<AttributesOnly<UserModel>>> {
|
||||
'INNER JOIN "account" ON "videoChannel"."accountId" = "account"."id" ' +
|
||||
`WHERE "account"."userId" = ${options.whereUserId} ${andWhere}`
|
||||
|
||||
const webtorrentFiles = 'SELECT "videoFile"."size" AS "size", "video"."id" AS "videoId" FROM "videoFile" ' +
|
||||
const webVideoFiles = 'SELECT "videoFile"."size" AS "size", "video"."id" AS "videoId" FROM "videoFile" ' +
|
||||
'INNER JOIN "video" ON "videoFile"."videoId" = "video"."id" AND "video"."isLive" IS FALSE ' +
|
||||
videoChannelJoin
|
||||
|
||||
@@ -797,7 +797,7 @@ export class UserModel extends Model<Partial<AttributesOnly<UserModel>>> {
|
||||
|
||||
return 'SELECT COALESCE(SUM("size"), 0) AS "total" ' +
|
||||
'FROM (' +
|
||||
`SELECT MAX("t1"."size") AS "size" FROM (${webtorrentFiles} UNION ${hlsFiles}) t1 ` +
|
||||
`SELECT MAX("t1"."size") AS "size" FROM (${webVideoFiles} UNION ${hlsFiles}) t1 ` +
|
||||
'GROUP BY "t1"."videoId"' +
|
||||
') t2'
|
||||
}
|
||||
@@ -890,8 +890,6 @@ export class UserModel extends Model<Partial<AttributesOnly<UserModel>>> {
|
||||
|
||||
nsfwPolicy: this.nsfwPolicy,
|
||||
|
||||
// FIXME: deprecated in 4.1
|
||||
webTorrentEnabled: this.p2pEnabled,
|
||||
p2pEnabled: this.p2pEnabled,
|
||||
|
||||
videosHistoryEnabled: this.videosHistoryEnabled,
|
||||
|
||||
@@ -111,7 +111,7 @@ export class AbstractVideoQueryBuilder extends AbstractRunQuery {
|
||||
}
|
||||
}
|
||||
|
||||
protected includeWebtorrentFiles () {
|
||||
protected includeWebVideoFiles () {
|
||||
this.addJoin('LEFT JOIN "videoFile" AS "VideoFiles" ON "VideoFiles"."videoId" = "video"."id"')
|
||||
|
||||
this.attributes = {
|
||||
@@ -263,7 +263,7 @@ export class AbstractVideoQueryBuilder extends AbstractRunQuery {
|
||||
}
|
||||
}
|
||||
|
||||
protected includeWebTorrentRedundancies () {
|
||||
protected includeWebVideoRedundancies () {
|
||||
this.addJoin(
|
||||
'LEFT OUTER JOIN "videoRedundancy" AS "VideoFiles->RedundancyVideos" ON ' +
|
||||
'"VideoFiles"."id" = "VideoFiles->RedundancyVideos"."videoFileId"'
|
||||
|
||||
@@ -14,7 +14,7 @@ export type FileQueryOptions = {
|
||||
|
||||
/**
|
||||
*
|
||||
* Fetch files (webtorrent and streaming playlist) according to a video
|
||||
* Fetch files (web videos and streaming playlist) according to a video
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -25,8 +25,8 @@ export class VideoFileQueryBuilder extends AbstractVideoQueryBuilder {
|
||||
super(sequelize, 'get')
|
||||
}
|
||||
|
||||
queryWebTorrentVideos (options: FileQueryOptions) {
|
||||
this.buildWebtorrentFilesQuery(options)
|
||||
queryWebVideos (options: FileQueryOptions) {
|
||||
this.buildWebVideoFilesQuery(options)
|
||||
|
||||
return this.runQuery(options)
|
||||
}
|
||||
@@ -37,15 +37,15 @@ export class VideoFileQueryBuilder extends AbstractVideoQueryBuilder {
|
||||
return this.runQuery(options)
|
||||
}
|
||||
|
||||
private buildWebtorrentFilesQuery (options: FileQueryOptions) {
|
||||
private buildWebVideoFilesQuery (options: FileQueryOptions) {
|
||||
this.attributes = {
|
||||
'"video"."id"': ''
|
||||
}
|
||||
|
||||
this.includeWebtorrentFiles()
|
||||
this.includeWebVideoFiles()
|
||||
|
||||
if (options.includeRedundancy) {
|
||||
this.includeWebTorrentRedundancies()
|
||||
this.includeWebVideoRedundancies()
|
||||
}
|
||||
|
||||
this.whereId(options)
|
||||
|
||||
@@ -60,10 +60,10 @@ export class VideoModelBuilder {
|
||||
buildVideosFromRows (options: {
|
||||
rows: SQLRow[]
|
||||
include?: VideoInclude
|
||||
rowsWebTorrentFiles?: SQLRow[]
|
||||
rowsWebVideoFiles?: SQLRow[]
|
||||
rowsStreamingPlaylist?: SQLRow[]
|
||||
}) {
|
||||
const { rows, rowsWebTorrentFiles, rowsStreamingPlaylist, include } = options
|
||||
const { rows, rowsWebVideoFiles, rowsStreamingPlaylist, include } = options
|
||||
|
||||
this.reinit()
|
||||
|
||||
@@ -85,8 +85,8 @@ export class VideoModelBuilder {
|
||||
this.addActorAvatar(row, 'VideoChannel.Account.Actor', accountActor)
|
||||
}
|
||||
|
||||
if (!rowsWebTorrentFiles) {
|
||||
this.addWebTorrentFile(row, videoModel)
|
||||
if (!rowsWebVideoFiles) {
|
||||
this.addWebVideoFile(row, videoModel)
|
||||
}
|
||||
|
||||
if (!rowsStreamingPlaylist) {
|
||||
@@ -112,7 +112,7 @@ export class VideoModelBuilder {
|
||||
}
|
||||
}
|
||||
|
||||
this.grabSeparateWebTorrentFiles(rowsWebTorrentFiles)
|
||||
this.grabSeparateWebVideoFiles(rowsWebVideoFiles)
|
||||
this.grabSeparateStreamingPlaylistFiles(rowsStreamingPlaylist)
|
||||
|
||||
return this.videos
|
||||
@@ -140,15 +140,15 @@ export class VideoModelBuilder {
|
||||
this.videos = []
|
||||
}
|
||||
|
||||
private grabSeparateWebTorrentFiles (rowsWebTorrentFiles?: SQLRow[]) {
|
||||
if (!rowsWebTorrentFiles) return
|
||||
private grabSeparateWebVideoFiles (rowsWebVideoFiles?: SQLRow[]) {
|
||||
if (!rowsWebVideoFiles) return
|
||||
|
||||
for (const row of rowsWebTorrentFiles) {
|
||||
for (const row of rowsWebVideoFiles) {
|
||||
const id = row['VideoFiles.id']
|
||||
if (!id) continue
|
||||
|
||||
const videoModel = this.videosMemo[row.id]
|
||||
this.addWebTorrentFile(row, videoModel)
|
||||
this.addWebVideoFile(row, videoModel)
|
||||
this.addRedundancy(row, 'VideoFiles', this.videoFileMemo[id])
|
||||
}
|
||||
}
|
||||
@@ -258,7 +258,7 @@ export class VideoModelBuilder {
|
||||
this.thumbnailsDone.add(id)
|
||||
}
|
||||
|
||||
private addWebTorrentFile (row: SQLRow, videoModel: VideoModel) {
|
||||
private addWebVideoFile (row: SQLRow, videoModel: VideoModel) {
|
||||
const id = row['VideoFiles.id']
|
||||
if (!id || this.videoFileMemo[id]) return
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@ export type BuildVideoGetQueryOptions = {
|
||||
|
||||
export class VideoModelGetQueryBuilder {
|
||||
videoQueryBuilder: VideosModelGetQuerySubBuilder
|
||||
webtorrentFilesQueryBuilder: VideoFileQueryBuilder
|
||||
webVideoFilesQueryBuilder: VideoFileQueryBuilder
|
||||
streamingPlaylistFilesQueryBuilder: VideoFileQueryBuilder
|
||||
|
||||
private readonly videoModelBuilder: VideoModelBuilder
|
||||
@@ -44,7 +44,7 @@ export class VideoModelGetQueryBuilder {
|
||||
|
||||
constructor (protected readonly sequelize: Sequelize) {
|
||||
this.videoQueryBuilder = new VideosModelGetQuerySubBuilder(sequelize)
|
||||
this.webtorrentFilesQueryBuilder = new VideoFileQueryBuilder(sequelize)
|
||||
this.webVideoFilesQueryBuilder = new VideoFileQueryBuilder(sequelize)
|
||||
this.streamingPlaylistFilesQueryBuilder = new VideoFileQueryBuilder(sequelize)
|
||||
|
||||
this.videoModelBuilder = new VideoModelBuilder('get', new VideoTableAttributes('get'))
|
||||
@@ -57,11 +57,11 @@ export class VideoModelGetQueryBuilder {
|
||||
includeRedundancy: this.shouldIncludeRedundancies(options)
|
||||
}
|
||||
|
||||
const [ videoRows, webtorrentFilesRows, streamingPlaylistFilesRows ] = await Promise.all([
|
||||
const [ videoRows, webVideoFilesRows, streamingPlaylistFilesRows ] = await Promise.all([
|
||||
this.videoQueryBuilder.queryVideos(options),
|
||||
|
||||
VideoModelGetQueryBuilder.videoFilesInclude.has(options.type)
|
||||
? this.webtorrentFilesQueryBuilder.queryWebTorrentVideos(fileQueryOptions)
|
||||
? this.webVideoFilesQueryBuilder.queryWebVideos(fileQueryOptions)
|
||||
: Promise.resolve(undefined),
|
||||
|
||||
VideoModelGetQueryBuilder.videoFilesInclude.has(options.type)
|
||||
@@ -71,7 +71,7 @@ export class VideoModelGetQueryBuilder {
|
||||
|
||||
const videos = this.videoModelBuilder.buildVideosFromRows({
|
||||
rows: videoRows,
|
||||
rowsWebTorrentFiles: webtorrentFilesRows,
|
||||
rowsWebVideoFiles: webVideoFilesRows,
|
||||
rowsStreamingPlaylist: streamingPlaylistFilesRows
|
||||
})
|
||||
|
||||
@@ -92,7 +92,7 @@ export class VideoModelGetQueryBuilder {
|
||||
export class VideosModelGetQuerySubBuilder extends AbstractVideoQueryBuilder {
|
||||
protected attributes: { [key: string]: string }
|
||||
|
||||
protected webtorrentFilesQuery: string
|
||||
protected webVideoFilesQuery: string
|
||||
protected streamingPlaylistFilesQuery: string
|
||||
|
||||
private static readonly trackersInclude = new Set<GetType>([ 'api' ])
|
||||
|
||||
@@ -48,7 +48,9 @@ export type BuildVideosListQueryOptions = {
|
||||
|
||||
hasFiles?: boolean
|
||||
hasHLSFiles?: boolean
|
||||
hasWebtorrentFiles?: boolean
|
||||
|
||||
hasWebVideoFiles?: boolean
|
||||
hasWebtorrentFiles?: boolean // TODO: Remove in v7
|
||||
|
||||
accountId?: number
|
||||
videoChannelId?: number
|
||||
@@ -175,7 +177,9 @@ export class VideosIdListQueryBuilder extends AbstractRunQuery {
|
||||
}
|
||||
|
||||
if (exists(options.hasWebtorrentFiles)) {
|
||||
this.whereWebTorrentFileExists(options.hasWebtorrentFiles)
|
||||
this.whereWebVideoFileExists(options.hasWebtorrentFiles)
|
||||
} else if (exists(options.hasWebVideoFiles)) {
|
||||
this.whereWebVideoFileExists(options.hasWebVideoFiles)
|
||||
}
|
||||
|
||||
if (exists(options.hasHLSFiles)) {
|
||||
@@ -400,18 +404,18 @@ export class VideosIdListQueryBuilder extends AbstractRunQuery {
|
||||
}
|
||||
|
||||
private whereFileExists () {
|
||||
this.and.push(`(${this.buildWebTorrentFileExistsQuery(true)} OR ${this.buildHLSFileExistsQuery(true)})`)
|
||||
this.and.push(`(${this.buildWebVideoFileExistsQuery(true)} OR ${this.buildHLSFileExistsQuery(true)})`)
|
||||
}
|
||||
|
||||
private whereWebTorrentFileExists (exists: boolean) {
|
||||
this.and.push(this.buildWebTorrentFileExistsQuery(exists))
|
||||
private whereWebVideoFileExists (exists: boolean) {
|
||||
this.and.push(this.buildWebVideoFileExistsQuery(exists))
|
||||
}
|
||||
|
||||
private whereHLSFileExists (exists: boolean) {
|
||||
this.and.push(this.buildHLSFileExistsQuery(exists))
|
||||
}
|
||||
|
||||
private buildWebTorrentFileExistsQuery (exists: boolean) {
|
||||
private buildWebVideoFileExistsQuery (exists: boolean) {
|
||||
const prefix = exists ? '' : 'NOT '
|
||||
|
||||
return prefix + 'EXISTS (SELECT 1 FROM "videoFile" WHERE "videoFile"."videoId" = "video"."id")'
|
||||
|
||||
@@ -18,7 +18,7 @@ export class VideosModelListQueryBuilder extends AbstractVideoQueryBuilder {
|
||||
private innerQuery: string
|
||||
private innerSort: string
|
||||
|
||||
webtorrentFilesQueryBuilder: VideoFileQueryBuilder
|
||||
webVideoFilesQueryBuilder: VideoFileQueryBuilder
|
||||
streamingPlaylistFilesQueryBuilder: VideoFileQueryBuilder
|
||||
|
||||
private readonly videoModelBuilder: VideoModelBuilder
|
||||
@@ -27,7 +27,7 @@ export class VideosModelListQueryBuilder extends AbstractVideoQueryBuilder {
|
||||
super(sequelize, 'list')
|
||||
|
||||
this.videoModelBuilder = new VideoModelBuilder(this.mode, this.tables)
|
||||
this.webtorrentFilesQueryBuilder = new VideoFileQueryBuilder(sequelize)
|
||||
this.webVideoFilesQueryBuilder = new VideoFileQueryBuilder(sequelize)
|
||||
this.streamingPlaylistFilesQueryBuilder = new VideoFileQueryBuilder(sequelize)
|
||||
}
|
||||
|
||||
@@ -48,12 +48,12 @@ export class VideosModelListQueryBuilder extends AbstractVideoQueryBuilder {
|
||||
includeRedundancy: false
|
||||
}
|
||||
|
||||
const [ rowsWebTorrentFiles, rowsStreamingPlaylist ] = await Promise.all([
|
||||
this.webtorrentFilesQueryBuilder.queryWebTorrentVideos(fileQueryOptions),
|
||||
const [ rowsWebVideoFiles, rowsStreamingPlaylist ] = await Promise.all([
|
||||
this.webVideoFilesQueryBuilder.queryWebVideos(fileQueryOptions),
|
||||
this.streamingPlaylistFilesQueryBuilder.queryStreamingPlaylistVideos(fileQueryOptions)
|
||||
])
|
||||
|
||||
return this.videoModelBuilder.buildVideosFromRows({ rows, include: options.include, rowsStreamingPlaylist, rowsWebTorrentFiles })
|
||||
return this.videoModelBuilder.buildVideosFromRows({ rows, include: options.include, rowsStreamingPlaylist, rowsWebVideoFiles })
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -45,7 +45,7 @@ enum ScopeNames {
|
||||
{
|
||||
model: VideoModel.scope([
|
||||
VideoScopeNames.WITH_THUMBNAILS,
|
||||
VideoScopeNames.WITH_WEBTORRENT_FILES,
|
||||
VideoScopeNames.WITH_WEB_VIDEO_FILES,
|
||||
VideoScopeNames.WITH_STREAMING_PLAYLISTS,
|
||||
VideoScopeNames.WITH_ACCOUNT_DETAILS
|
||||
]),
|
||||
|
||||
@@ -26,8 +26,8 @@ import { buildRemoteVideoBaseUrl } from '@server/lib/activitypub/url'
|
||||
import {
|
||||
getHLSPrivateFileUrl,
|
||||
getHLSPublicFileUrl,
|
||||
getWebTorrentPrivateFileUrl,
|
||||
getWebTorrentPublicFileUrl
|
||||
getWebVideoPrivateFileUrl,
|
||||
getWebVideoPublicFileUrl
|
||||
} from '@server/lib/object-storage'
|
||||
import { getFSTorrentFilePath } from '@server/lib/paths'
|
||||
import { isVideoInPrivateDirectory } from '@server/lib/video-privacy'
|
||||
@@ -276,15 +276,15 @@ export class VideoFileModel extends Model<Partial<AttributesOnly<VideoFileModel>
|
||||
|
||||
static async doesOwnedTorrentFileExist (filename: string) {
|
||||
const query = 'SELECT 1 FROM "videoFile" ' +
|
||||
'LEFT JOIN "video" "webtorrent" ON "webtorrent"."id" = "videoFile"."videoId" AND "webtorrent"."remote" IS FALSE ' +
|
||||
'LEFT JOIN "video" "webvideo" ON "webvideo"."id" = "videoFile"."videoId" AND "webvideo"."remote" IS FALSE ' +
|
||||
'LEFT JOIN "videoStreamingPlaylist" ON "videoStreamingPlaylist"."id" = "videoFile"."videoStreamingPlaylistId" ' +
|
||||
'LEFT JOIN "video" "hlsVideo" ON "hlsVideo"."id" = "videoStreamingPlaylist"."videoId" AND "hlsVideo"."remote" IS FALSE ' +
|
||||
'WHERE "torrentFilename" = $filename AND ("hlsVideo"."id" IS NOT NULL OR "webtorrent"."id" IS NOT NULL) LIMIT 1'
|
||||
'WHERE "torrentFilename" = $filename AND ("hlsVideo"."id" IS NOT NULL OR "webvideo"."id" IS NOT NULL) LIMIT 1'
|
||||
|
||||
return doesExist(this.sequelize, query, { filename })
|
||||
}
|
||||
|
||||
static async doesOwnedWebTorrentVideoFileExist (filename: string) {
|
||||
static async doesOwnedWebVideoFileExist (filename: string) {
|
||||
const query = 'SELECT 1 FROM "videoFile" INNER JOIN "video" ON "video"."id" = "videoFile"."videoId" AND "video"."remote" IS FALSE ' +
|
||||
`WHERE "filename" = $filename AND "storage" = ${VideoStorage.FILE_SYSTEM} LIMIT 1`
|
||||
|
||||
@@ -378,7 +378,7 @@ export class VideoFileModel extends Model<Partial<AttributesOnly<VideoFileModel>
|
||||
}
|
||||
|
||||
static getStats () {
|
||||
const webtorrentFilesQuery: FindOptions = {
|
||||
const webVideoFilesQuery: FindOptions = {
|
||||
include: [
|
||||
{
|
||||
attributes: [],
|
||||
@@ -412,10 +412,10 @@ export class VideoFileModel extends Model<Partial<AttributesOnly<VideoFileModel>
|
||||
}
|
||||
|
||||
return Promise.all([
|
||||
VideoFileModel.aggregate('size', 'SUM', webtorrentFilesQuery),
|
||||
VideoFileModel.aggregate('size', 'SUM', webVideoFilesQuery),
|
||||
VideoFileModel.aggregate('size', 'SUM', hlsFilesQuery)
|
||||
]).then(([ webtorrentResult, hlsResult ]) => ({
|
||||
totalLocalVideoFilesSize: parseAggregateResult(webtorrentResult) + parseAggregateResult(hlsResult)
|
||||
]).then(([ webVideoResult, hlsResult ]) => ({
|
||||
totalLocalVideoFilesSize: parseAggregateResult(webVideoResult) + parseAggregateResult(hlsResult)
|
||||
}))
|
||||
}
|
||||
|
||||
@@ -433,7 +433,7 @@ export class VideoFileModel extends Model<Partial<AttributesOnly<VideoFileModel>
|
||||
|
||||
const element = mode === 'streaming-playlist'
|
||||
? await VideoFileModel.loadHLSFile({ ...baseFind, playlistId: videoFile.videoStreamingPlaylistId })
|
||||
: await VideoFileModel.loadWebTorrentFile({ ...baseFind, videoId: videoFile.videoId })
|
||||
: await VideoFileModel.loadWebVideoFile({ ...baseFind, videoId: videoFile.videoId })
|
||||
|
||||
if (!element) return videoFile.save({ transaction })
|
||||
|
||||
@@ -444,7 +444,7 @@ export class VideoFileModel extends Model<Partial<AttributesOnly<VideoFileModel>
|
||||
return element.save({ transaction })
|
||||
}
|
||||
|
||||
static async loadWebTorrentFile (options: {
|
||||
static async loadWebVideoFile (options: {
|
||||
videoId: number
|
||||
fps: number
|
||||
resolution: number
|
||||
@@ -523,7 +523,7 @@ export class VideoFileModel extends Model<Partial<AttributesOnly<VideoFileModel>
|
||||
return getHLSPrivateFileUrl(video, this.filename)
|
||||
}
|
||||
|
||||
return getWebTorrentPrivateFileUrl(this.filename)
|
||||
return getWebVideoPrivateFileUrl(this.filename)
|
||||
}
|
||||
|
||||
private getPublicObjectStorageUrl () {
|
||||
@@ -531,7 +531,7 @@ export class VideoFileModel extends Model<Partial<AttributesOnly<VideoFileModel>
|
||||
return getHLSPublicFileUrl(this.fileUrl)
|
||||
}
|
||||
|
||||
return getWebTorrentPublicFileUrl(this.fileUrl)
|
||||
return getWebVideoPublicFileUrl(this.fileUrl)
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
@@ -553,10 +553,10 @@ export class VideoFileModel extends Model<Partial<AttributesOnly<VideoFileModel>
|
||||
getFileStaticPath (video: MVideo) {
|
||||
if (this.isHLS()) return this.getHLSFileStaticPath(video)
|
||||
|
||||
return this.getWebTorrentFileStaticPath(video)
|
||||
return this.getWebVideoFileStaticPath(video)
|
||||
}
|
||||
|
||||
private getWebTorrentFileStaticPath (video: MVideo) {
|
||||
private getWebVideoFileStaticPath (video: MVideo) {
|
||||
if (isVideoInPrivateDirectory(video.privacy)) {
|
||||
return join(STATIC_PATHS.PRIVATE_WEBSEED, this.filename)
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ import {
|
||||
import { getPrivaciesForFederation, isPrivacyForFederation, isStateForFederation } from '@server/helpers/video'
|
||||
import { InternalEventEmitter } from '@server/lib/internal-event-emitter'
|
||||
import { LiveManager } from '@server/lib/live/live-manager'
|
||||
import { removeHLSFileObjectStorageByFilename, removeHLSObjectStorage, removeWebTorrentObjectStorage } from '@server/lib/object-storage'
|
||||
import { removeHLSFileObjectStorageByFilename, removeHLSObjectStorage, removeWebVideoObjectStorage } from '@server/lib/object-storage'
|
||||
import { tracer } from '@server/lib/opentelemetry/tracing'
|
||||
import { getHLSDirectory, getHLSRedundancyDirectory, getHlsResolutionPlaylistFilename } from '@server/lib/paths'
|
||||
import { Hooks } from '@server/lib/plugins/hooks'
|
||||
@@ -151,7 +151,7 @@ export enum ScopeNames {
|
||||
FOR_API = 'FOR_API',
|
||||
WITH_ACCOUNT_DETAILS = 'WITH_ACCOUNT_DETAILS',
|
||||
WITH_TAGS = 'WITH_TAGS',
|
||||
WITH_WEBTORRENT_FILES = 'WITH_WEBTORRENT_FILES',
|
||||
WITH_WEB_VIDEO_FILES = 'WITH_WEB_VIDEO_FILES',
|
||||
WITH_SCHEDULED_UPDATE = 'WITH_SCHEDULED_UPDATE',
|
||||
WITH_BLACKLISTED = 'WITH_BLACKLISTED',
|
||||
WITH_STREAMING_PLAYLISTS = 'WITH_STREAMING_PLAYLISTS',
|
||||
@@ -290,7 +290,7 @@ export type ForAPIOptions = {
|
||||
}
|
||||
]
|
||||
},
|
||||
[ScopeNames.WITH_WEBTORRENT_FILES]: (withRedundancies = false) => {
|
||||
[ScopeNames.WITH_WEB_VIDEO_FILES]: (withRedundancies = false) => {
|
||||
let subInclude: any[] = []
|
||||
|
||||
if (withRedundancies === true) {
|
||||
@@ -813,7 +813,7 @@ export class VideoModel extends Model<Partial<AttributesOnly<VideoModel>>> {
|
||||
|
||||
// Remove physical files and torrents
|
||||
instance.VideoFiles.forEach(file => {
|
||||
tasks.push(instance.removeWebTorrentFile(file))
|
||||
tasks.push(instance.removeWebVideoFile(file))
|
||||
})
|
||||
|
||||
// Remove playlists file
|
||||
@@ -1107,7 +1107,10 @@ export class VideoModel extends Model<Partial<AttributesOnly<VideoModel>>> {
|
||||
include?: VideoInclude
|
||||
|
||||
hasFiles?: boolean // default false
|
||||
hasWebtorrentFiles?: boolean
|
||||
|
||||
hasWebtorrentFiles?: boolean // TODO: remove in v7
|
||||
hasWebVideoFiles?: boolean
|
||||
|
||||
hasHLSFiles?: boolean
|
||||
|
||||
categoryOneOf?: number[]
|
||||
@@ -1172,6 +1175,7 @@ export class VideoModel extends Model<Partial<AttributesOnly<VideoModel>>> {
|
||||
'historyOfUser',
|
||||
'hasHLSFiles',
|
||||
'hasWebtorrentFiles',
|
||||
'hasWebVideoFiles',
|
||||
'search',
|
||||
'excludeAlreadyWatched'
|
||||
]),
|
||||
@@ -1205,7 +1209,9 @@ export class VideoModel extends Model<Partial<AttributesOnly<VideoModel>>> {
|
||||
|
||||
user?: MUserAccountId
|
||||
|
||||
hasWebtorrentFiles?: boolean
|
||||
hasWebtorrentFiles?: boolean // TODO: remove in v7
|
||||
hasWebVideoFiles?: boolean
|
||||
|
||||
hasHLSFiles?: boolean
|
||||
|
||||
search?: string
|
||||
@@ -1252,6 +1258,7 @@ export class VideoModel extends Model<Partial<AttributesOnly<VideoModel>>> {
|
||||
'durationMax',
|
||||
'hasHLSFiles',
|
||||
'hasWebtorrentFiles',
|
||||
'hasWebVideoFiles',
|
||||
'uuids',
|
||||
'search',
|
||||
'displayOnlyForFollower',
|
||||
@@ -1676,7 +1683,7 @@ export class VideoModel extends Model<Partial<AttributesOnly<VideoModel>>> {
|
||||
return this.getQualityFileBy(minBy)
|
||||
}
|
||||
|
||||
getWebTorrentFile<T extends MVideoWithFile> (this: T, resolution: number): MVideoFileVideo {
|
||||
getWebVideoFile<T extends MVideoWithFile> (this: T, resolution: number): MVideoFileVideo {
|
||||
if (Array.isArray(this.VideoFiles) === false) return undefined
|
||||
|
||||
const file = this.VideoFiles.find(f => f.resolution === resolution)
|
||||
@@ -1685,7 +1692,7 @@ export class VideoModel extends Model<Partial<AttributesOnly<VideoModel>>> {
|
||||
return Object.assign(file, { Video: this })
|
||||
}
|
||||
|
||||
hasWebTorrentFiles () {
|
||||
hasWebVideoFiles () {
|
||||
return Array.isArray(this.VideoFiles) === true && this.VideoFiles.length !== 0
|
||||
}
|
||||
|
||||
@@ -1884,7 +1891,7 @@ export class VideoModel extends Model<Partial<AttributesOnly<VideoModel>>> {
|
||||
.concat(toAdd)
|
||||
}
|
||||
|
||||
removeWebTorrentFile (videoFile: MVideoFile, isRedundancy = false) {
|
||||
removeWebVideoFile (videoFile: MVideoFile, isRedundancy = false) {
|
||||
const filePath = isRedundancy
|
||||
? VideoPathManager.Instance.getFSRedundancyVideoFilePath(this, videoFile)
|
||||
: VideoPathManager.Instance.getFSVideoFileOutputPath(this, videoFile)
|
||||
@@ -1893,7 +1900,7 @@ export class VideoModel extends Model<Partial<AttributesOnly<VideoModel>>> {
|
||||
if (!isRedundancy) promises.push(videoFile.removeTorrent())
|
||||
|
||||
if (videoFile.storage === VideoStorage.OBJECT_STORAGE) {
|
||||
promises.push(removeWebTorrentObjectStorage(videoFile))
|
||||
promises.push(removeWebVideoObjectStorage(videoFile))
|
||||
}
|
||||
|
||||
return Promise.all(promises)
|
||||
|
||||
@@ -345,7 +345,7 @@ describe('Test config API validators', function () {
|
||||
})
|
||||
})
|
||||
|
||||
it('Should fail with a disabled webtorrent & hls transcoding', async function () {
|
||||
it('Should fail with a disabled web videos & hls transcoding', async function () {
|
||||
const newUpdateParams = {
|
||||
...updateParams,
|
||||
|
||||
|
||||
@@ -49,21 +49,21 @@ describe('Test transcoding API validators', function () {
|
||||
|
||||
it('Should not run transcoding of a unknown video', async function () {
|
||||
await servers[0].videos.runTranscoding({ videoId: 404, transcodingType: 'hls', expectedStatus: HttpStatusCode.NOT_FOUND_404 })
|
||||
await servers[0].videos.runTranscoding({ videoId: 404, transcodingType: 'webtorrent', expectedStatus: HttpStatusCode.NOT_FOUND_404 })
|
||||
await servers[0].videos.runTranscoding({ videoId: 404, transcodingType: 'web-video', expectedStatus: HttpStatusCode.NOT_FOUND_404 })
|
||||
})
|
||||
|
||||
it('Should not run transcoding of a remote video', async function () {
|
||||
const expectedStatus = HttpStatusCode.BAD_REQUEST_400
|
||||
|
||||
await servers[0].videos.runTranscoding({ videoId: remoteId, transcodingType: 'hls', expectedStatus })
|
||||
await servers[0].videos.runTranscoding({ videoId: remoteId, transcodingType: 'webtorrent', expectedStatus })
|
||||
await servers[0].videos.runTranscoding({ videoId: remoteId, transcodingType: 'web-video', expectedStatus })
|
||||
})
|
||||
|
||||
it('Should not run transcoding by a non admin user', async function () {
|
||||
const expectedStatus = HttpStatusCode.FORBIDDEN_403
|
||||
|
||||
await servers[0].videos.runTranscoding({ videoId: validId, transcodingType: 'hls', token: userToken, expectedStatus })
|
||||
await servers[0].videos.runTranscoding({ videoId: validId, transcodingType: 'webtorrent', token: moderatorToken, expectedStatus })
|
||||
await servers[0].videos.runTranscoding({ videoId: validId, transcodingType: 'web-video', token: moderatorToken, expectedStatus })
|
||||
})
|
||||
|
||||
it('Should not run transcoding without transcoding type', async function () {
|
||||
@@ -82,7 +82,7 @@ describe('Test transcoding API validators', function () {
|
||||
await servers[0].config.disableTranscoding()
|
||||
|
||||
await servers[0].videos.runTranscoding({ videoId: validId, transcodingType: 'hls', expectedStatus })
|
||||
await servers[0].videos.runTranscoding({ videoId: validId, transcodingType: 'webtorrent', expectedStatus })
|
||||
await servers[0].videos.runTranscoding({ videoId: validId, transcodingType: 'web-video', expectedStatus })
|
||||
})
|
||||
|
||||
it('Should run transcoding', async function () {
|
||||
@@ -93,15 +93,15 @@ describe('Test transcoding API validators', function () {
|
||||
await servers[0].videos.runTranscoding({ videoId: validId, transcodingType: 'hls' })
|
||||
await waitJobs(servers)
|
||||
|
||||
await servers[0].videos.runTranscoding({ videoId: validId, transcodingType: 'webtorrent' })
|
||||
await servers[0].videos.runTranscoding({ videoId: validId, transcodingType: 'web-video' })
|
||||
await waitJobs(servers)
|
||||
})
|
||||
|
||||
it('Should not run transcoding on a video that is already being transcoded', async function () {
|
||||
await servers[0].videos.runTranscoding({ videoId: validId, transcodingType: 'webtorrent' })
|
||||
await servers[0].videos.runTranscoding({ videoId: validId, transcodingType: 'web-video' })
|
||||
|
||||
const expectedStatus = HttpStatusCode.CONFLICT_409
|
||||
await servers[0].videos.runTranscoding({ videoId: validId, transcodingType: 'webtorrent', expectedStatus })
|
||||
await servers[0].videos.runTranscoding({ videoId: validId, transcodingType: 'web-video', expectedStatus })
|
||||
})
|
||||
|
||||
after(async function () {
|
||||
|
||||
@@ -60,7 +60,7 @@ describe('Test videos files', function () {
|
||||
})
|
||||
|
||||
describe('Deleting files', function () {
|
||||
let webtorrentId: string
|
||||
let webVideoId: string
|
||||
let hlsId: string
|
||||
let remoteId: string
|
||||
|
||||
@@ -68,10 +68,10 @@ describe('Test videos files', function () {
|
||||
let validId2: string
|
||||
|
||||
let hlsFileId: number
|
||||
let webtorrentFileId: number
|
||||
let webVideoFileId: number
|
||||
|
||||
let remoteHLSFileId: number
|
||||
let remoteWebtorrentFileId: number
|
||||
let remoteWebVideoFileId: number
|
||||
|
||||
before(async function () {
|
||||
this.timeout(300_000)
|
||||
@@ -83,7 +83,7 @@ describe('Test videos files', function () {
|
||||
const video = await servers[1].videos.get({ id: uuid })
|
||||
remoteId = video.uuid
|
||||
remoteHLSFileId = video.streamingPlaylists[0].files[0].id
|
||||
remoteWebtorrentFileId = video.files[0].id
|
||||
remoteWebVideoFileId = video.files[0].id
|
||||
}
|
||||
|
||||
{
|
||||
@@ -96,7 +96,7 @@ describe('Test videos files', function () {
|
||||
const video = await servers[0].videos.get({ id: uuid })
|
||||
validId1 = video.uuid
|
||||
hlsFileId = video.streamingPlaylists[0].files[0].id
|
||||
webtorrentFileId = video.files[0].id
|
||||
webVideoFileId = video.files[0].id
|
||||
}
|
||||
|
||||
{
|
||||
@@ -117,8 +117,8 @@ describe('Test videos files', function () {
|
||||
|
||||
{
|
||||
await servers[0].config.enableTranscoding(false, true)
|
||||
const { uuid } = await servers[0].videos.quickUpload({ name: 'webtorrent' })
|
||||
webtorrentId = uuid
|
||||
const { uuid } = await servers[0].videos.quickUpload({ name: 'web-video' })
|
||||
webVideoId = uuid
|
||||
}
|
||||
|
||||
await waitJobs(servers)
|
||||
@@ -128,27 +128,27 @@ describe('Test videos files', function () {
|
||||
const expectedStatus = HttpStatusCode.NOT_FOUND_404
|
||||
|
||||
await servers[0].videos.removeHLSPlaylist({ videoId: 404, expectedStatus })
|
||||
await servers[0].videos.removeAllWebTorrentFiles({ videoId: 404, expectedStatus })
|
||||
await servers[0].videos.removeAllWebVideoFiles({ videoId: 404, expectedStatus })
|
||||
|
||||
await servers[0].videos.removeHLSFile({ videoId: 404, fileId: hlsFileId, expectedStatus })
|
||||
await servers[0].videos.removeWebTorrentFile({ videoId: 404, fileId: webtorrentFileId, expectedStatus })
|
||||
await servers[0].videos.removeWebVideoFile({ videoId: 404, fileId: webVideoFileId, expectedStatus })
|
||||
})
|
||||
|
||||
it('Should not delete unknown files', async function () {
|
||||
const expectedStatus = HttpStatusCode.NOT_FOUND_404
|
||||
|
||||
await servers[0].videos.removeHLSFile({ videoId: validId1, fileId: webtorrentFileId, expectedStatus })
|
||||
await servers[0].videos.removeWebTorrentFile({ videoId: validId1, fileId: hlsFileId, expectedStatus })
|
||||
await servers[0].videos.removeHLSFile({ videoId: validId1, fileId: webVideoFileId, expectedStatus })
|
||||
await servers[0].videos.removeWebVideoFile({ videoId: validId1, fileId: hlsFileId, expectedStatus })
|
||||
})
|
||||
|
||||
it('Should not delete files of a remote video', async function () {
|
||||
const expectedStatus = HttpStatusCode.BAD_REQUEST_400
|
||||
|
||||
await servers[0].videos.removeHLSPlaylist({ videoId: remoteId, expectedStatus })
|
||||
await servers[0].videos.removeAllWebTorrentFiles({ videoId: remoteId, expectedStatus })
|
||||
await servers[0].videos.removeAllWebVideoFiles({ videoId: remoteId, expectedStatus })
|
||||
|
||||
await servers[0].videos.removeHLSFile({ videoId: remoteId, fileId: remoteHLSFileId, expectedStatus })
|
||||
await servers[0].videos.removeWebTorrentFile({ videoId: remoteId, fileId: remoteWebtorrentFileId, expectedStatus })
|
||||
await servers[0].videos.removeWebVideoFile({ videoId: remoteId, fileId: remoteWebVideoFileId, expectedStatus })
|
||||
})
|
||||
|
||||
it('Should not delete files by a non admin user', async function () {
|
||||
@@ -157,35 +157,35 @@ describe('Test videos files', function () {
|
||||
await servers[0].videos.removeHLSPlaylist({ videoId: validId1, token: userToken, expectedStatus })
|
||||
await servers[0].videos.removeHLSPlaylist({ videoId: validId1, token: moderatorToken, expectedStatus })
|
||||
|
||||
await servers[0].videos.removeAllWebTorrentFiles({ videoId: validId1, token: userToken, expectedStatus })
|
||||
await servers[0].videos.removeAllWebTorrentFiles({ videoId: validId1, token: moderatorToken, expectedStatus })
|
||||
await servers[0].videos.removeAllWebVideoFiles({ videoId: validId1, token: userToken, expectedStatus })
|
||||
await servers[0].videos.removeAllWebVideoFiles({ videoId: validId1, token: moderatorToken, expectedStatus })
|
||||
|
||||
await servers[0].videos.removeHLSFile({ videoId: validId1, fileId: hlsFileId, token: userToken, expectedStatus })
|
||||
await servers[0].videos.removeHLSFile({ videoId: validId1, fileId: hlsFileId, token: moderatorToken, expectedStatus })
|
||||
|
||||
await servers[0].videos.removeWebTorrentFile({ videoId: validId1, fileId: webtorrentFileId, token: userToken, expectedStatus })
|
||||
await servers[0].videos.removeWebTorrentFile({ videoId: validId1, fileId: webtorrentFileId, token: moderatorToken, expectedStatus })
|
||||
await servers[0].videos.removeWebVideoFile({ videoId: validId1, fileId: webVideoFileId, token: userToken, expectedStatus })
|
||||
await servers[0].videos.removeWebVideoFile({ videoId: validId1, fileId: webVideoFileId, token: moderatorToken, expectedStatus })
|
||||
})
|
||||
|
||||
it('Should not delete files if the files are not available', async function () {
|
||||
await servers[0].videos.removeHLSPlaylist({ videoId: hlsId, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
|
||||
await servers[0].videos.removeAllWebTorrentFiles({ videoId: webtorrentId, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
|
||||
await servers[0].videos.removeAllWebVideoFiles({ videoId: webVideoId, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
|
||||
|
||||
await servers[0].videos.removeHLSFile({ videoId: hlsId, fileId: 404, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
|
||||
await servers[0].videos.removeWebTorrentFile({ videoId: webtorrentId, fileId: 404, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
|
||||
await servers[0].videos.removeWebVideoFile({ videoId: webVideoId, fileId: 404, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
|
||||
})
|
||||
|
||||
it('Should not delete files if no both versions are available', async function () {
|
||||
await servers[0].videos.removeHLSPlaylist({ videoId: hlsId, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
|
||||
await servers[0].videos.removeAllWebTorrentFiles({ videoId: webtorrentId, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
|
||||
await servers[0].videos.removeAllWebVideoFiles({ videoId: webVideoId, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
|
||||
})
|
||||
|
||||
it('Should delete files if both versions are available', async function () {
|
||||
await servers[0].videos.removeHLSFile({ videoId: validId1, fileId: hlsFileId })
|
||||
await servers[0].videos.removeWebTorrentFile({ videoId: validId1, fileId: webtorrentFileId })
|
||||
await servers[0].videos.removeWebVideoFile({ videoId: validId1, fileId: webVideoFileId })
|
||||
|
||||
await servers[0].videos.removeHLSPlaylist({ videoId: validId1 })
|
||||
await servers[0].videos.removeAllWebTorrentFiles({ videoId: validId2 })
|
||||
await servers[0].videos.removeAllWebVideoFiles({ videoId: validId2 })
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
@@ -120,7 +120,7 @@ describe('Object storage for video static file privacy', function () {
|
||||
const video = await server.videos.getWithToken({ id: videoId })
|
||||
|
||||
return {
|
||||
webTorrentFile: video.files[0].fileUrl,
|
||||
webVideoFile: video.files[0].fileUrl,
|
||||
hlsFile: getHLS(video).files[0].fileUrl
|
||||
}
|
||||
}
|
||||
@@ -175,10 +175,10 @@ describe('Object storage for video static file privacy', function () {
|
||||
it('Should not get files without appropriate OAuth token', async function () {
|
||||
this.timeout(60000)
|
||||
|
||||
const { webTorrentFile, hlsFile } = await getSampleFileUrls(privateVideoUUID)
|
||||
const { webVideoFile, hlsFile } = await getSampleFileUrls(privateVideoUUID)
|
||||
|
||||
await makeRawRequest({ url: webTorrentFile, token: userToken, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
|
||||
await makeRawRequest({ url: webTorrentFile, token: server.accessToken, expectedStatus: HttpStatusCode.OK_200 })
|
||||
await makeRawRequest({ url: webVideoFile, token: userToken, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
|
||||
await makeRawRequest({ url: webVideoFile, token: server.accessToken, expectedStatus: HttpStatusCode.OK_200 })
|
||||
|
||||
await makeRawRequest({ url: hlsFile, token: userToken, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
|
||||
await makeRawRequest({ url: hlsFile, token: server.accessToken, expectedStatus: HttpStatusCode.OK_200 })
|
||||
@@ -187,18 +187,18 @@ describe('Object storage for video static file privacy', function () {
|
||||
it('Should not get files without appropriate password or appropriate OAuth token', async function () {
|
||||
this.timeout(60000)
|
||||
|
||||
const { webTorrentFile, hlsFile } = await getSampleFileUrls(passwordProtectedVideoUUID)
|
||||
const { webVideoFile, hlsFile } = await getSampleFileUrls(passwordProtectedVideoUUID)
|
||||
|
||||
await makeRawRequest({ url: webTorrentFile, token: userToken, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
|
||||
await makeRawRequest({ url: webVideoFile, token: userToken, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
|
||||
await makeRawRequest({
|
||||
url: webTorrentFile,
|
||||
url: webVideoFile,
|
||||
token: null,
|
||||
headers: incorrectPasswordHeader,
|
||||
expectedStatus: HttpStatusCode.FORBIDDEN_403
|
||||
})
|
||||
await makeRawRequest({ url: webTorrentFile, token: server.accessToken, expectedStatus: HttpStatusCode.OK_200 })
|
||||
await makeRawRequest({ url: webVideoFile, token: server.accessToken, expectedStatus: HttpStatusCode.OK_200 })
|
||||
await makeRawRequest({
|
||||
url: webTorrentFile,
|
||||
url: webVideoFile,
|
||||
token: null,
|
||||
headers: correctPasswordHeader,
|
||||
expectedStatus: HttpStatusCode.OK_200
|
||||
@@ -239,9 +239,9 @@ describe('Object storage for video static file privacy', function () {
|
||||
const badVideoFileToken = await server.videoToken.getVideoFileToken({ token: userToken, videoId: userPrivateVideoUUID })
|
||||
const goodVideoFileToken = await server.videoToken.getVideoFileToken({ videoId: privateVideoUUID })
|
||||
|
||||
const { webTorrentFile, hlsFile } = await getSampleFileUrls(privateVideoUUID)
|
||||
const { webVideoFile, hlsFile } = await getSampleFileUrls(privateVideoUUID)
|
||||
|
||||
for (const url of [ webTorrentFile, hlsFile ]) {
|
||||
for (const url of [ webVideoFile, hlsFile ]) {
|
||||
await makeRawRequest({ url, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
|
||||
await makeRawRequest({ url, token: userToken, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
|
||||
await makeRawRequest({ url, token: server.accessToken, expectedStatus: HttpStatusCode.OK_200 })
|
||||
@@ -261,9 +261,9 @@ describe('Object storage for video static file privacy', function () {
|
||||
videoPassword: correctPassword
|
||||
})
|
||||
|
||||
const { webTorrentFile, hlsFile } = await getSampleFileUrls(passwordProtectedVideoUUID)
|
||||
const { webVideoFile, hlsFile } = await getSampleFileUrls(passwordProtectedVideoUUID)
|
||||
|
||||
for (const url of [ hlsFile, webTorrentFile ]) {
|
||||
for (const url of [ hlsFile, webVideoFile ]) {
|
||||
await makeRawRequest({ url, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
|
||||
await makeRawRequest({ url, token: userToken, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
|
||||
await makeRawRequest({ url, token: server.accessToken, expectedStatus: HttpStatusCode.OK_200 })
|
||||
@@ -534,11 +534,11 @@ describe('Object storage for video static file privacy', function () {
|
||||
|
||||
it('Should not be able to access object storage proxy', async function () {
|
||||
const privateVideo = await server.videos.getWithToken({ id: videoUUID })
|
||||
const webtorrentFilename = extractFilenameFromUrl(privateVideo.files[0].fileUrl)
|
||||
const webVideoFilename = extractFilenameFromUrl(privateVideo.files[0].fileUrl)
|
||||
const hlsFilename = extractFilenameFromUrl(getHLS(privateVideo).files[0].fileUrl)
|
||||
|
||||
await makeRawRequest({
|
||||
url: server.url + '/object-storage-proxy/webseed/private/' + webtorrentFilename,
|
||||
url: server.url + '/object-storage-proxy/webseed/private/' + webVideoFilename,
|
||||
token: server.accessToken,
|
||||
expectedStatus: HttpStatusCode.BAD_REQUEST_400
|
||||
})
|
||||
|
||||
@@ -41,8 +41,8 @@ async function checkFiles (options: {
|
||||
playlistBucket: string
|
||||
playlistPrefix?: string
|
||||
|
||||
webtorrentBucket: string
|
||||
webtorrentPrefix?: string
|
||||
webVideoBucket: string
|
||||
webVideoPrefix?: string
|
||||
}) {
|
||||
const {
|
||||
server,
|
||||
@@ -50,20 +50,20 @@ async function checkFiles (options: {
|
||||
originSQLCommand,
|
||||
video,
|
||||
playlistBucket,
|
||||
webtorrentBucket,
|
||||
webVideoBucket,
|
||||
baseMockUrl,
|
||||
playlistPrefix,
|
||||
webtorrentPrefix
|
||||
webVideoPrefix
|
||||
} = options
|
||||
|
||||
let allFiles = video.files
|
||||
|
||||
for (const file of video.files) {
|
||||
const baseUrl = baseMockUrl
|
||||
? `${baseMockUrl}/${webtorrentBucket}/`
|
||||
: `http://${webtorrentBucket}.${ObjectStorageCommand.getMockEndpointHost()}/`
|
||||
? `${baseMockUrl}/${webVideoBucket}/`
|
||||
: `http://${webVideoBucket}.${ObjectStorageCommand.getMockEndpointHost()}/`
|
||||
|
||||
const prefix = webtorrentPrefix || ''
|
||||
const prefix = webVideoPrefix || ''
|
||||
const start = baseUrl + prefix
|
||||
|
||||
expectStartWith(file.fileUrl, start)
|
||||
@@ -134,8 +134,8 @@ function runTestSuite (options: {
|
||||
playlistBucket: string
|
||||
playlistPrefix?: string
|
||||
|
||||
webtorrentBucket: string
|
||||
webtorrentPrefix?: string
|
||||
webVideoBucket: string
|
||||
webVideoPrefix?: string
|
||||
|
||||
useMockBaseUrl?: boolean
|
||||
}) {
|
||||
@@ -161,7 +161,7 @@ function runTestSuite (options: {
|
||||
: undefined
|
||||
|
||||
await objectStorage.createMockBucket(options.playlistBucket)
|
||||
await objectStorage.createMockBucket(options.webtorrentBucket)
|
||||
await objectStorage.createMockBucket(options.webVideoBucket)
|
||||
|
||||
const config = {
|
||||
object_storage: {
|
||||
@@ -182,10 +182,10 @@ function runTestSuite (options: {
|
||||
},
|
||||
|
||||
videos: {
|
||||
bucket_name: options.webtorrentBucket,
|
||||
prefix: options.webtorrentPrefix,
|
||||
bucket_name: options.webVideoBucket,
|
||||
prefix: options.webVideoPrefix,
|
||||
base_url: baseMockUrl
|
||||
? `${baseMockUrl}/${options.webtorrentBucket}`
|
||||
? `${baseMockUrl}/${options.webVideoBucket}`
|
||||
: undefined
|
||||
}
|
||||
}
|
||||
@@ -386,27 +386,27 @@ describe('Object storage for videos', function () {
|
||||
describe('Test simple object storage', function () {
|
||||
runTestSuite({
|
||||
playlistBucket: objectStorage.getMockBucketName('streaming-playlists'),
|
||||
webtorrentBucket: objectStorage.getMockBucketName('videos')
|
||||
webVideoBucket: objectStorage.getMockBucketName('videos')
|
||||
})
|
||||
})
|
||||
|
||||
describe('Test object storage with prefix', function () {
|
||||
runTestSuite({
|
||||
playlistBucket: objectStorage.getMockBucketName('mybucket'),
|
||||
webtorrentBucket: objectStorage.getMockBucketName('mybucket'),
|
||||
webVideoBucket: objectStorage.getMockBucketName('mybucket'),
|
||||
|
||||
playlistPrefix: 'streaming-playlists_',
|
||||
webtorrentPrefix: 'webtorrent_'
|
||||
webVideoPrefix: 'webvideo_'
|
||||
})
|
||||
})
|
||||
|
||||
describe('Test object storage with prefix and base URL', function () {
|
||||
runTestSuite({
|
||||
playlistBucket: objectStorage.getMockBucketName('mybucket'),
|
||||
webtorrentBucket: objectStorage.getMockBucketName('mybucket'),
|
||||
webVideoBucket: objectStorage.getMockBucketName('mybucket'),
|
||||
|
||||
playlistPrefix: 'streaming-playlists/',
|
||||
webtorrentPrefix: 'webtorrent/',
|
||||
webVideoPrefix: 'webvideo/',
|
||||
|
||||
useMockBaseUrl: true
|
||||
})
|
||||
@@ -431,7 +431,7 @@ describe('Object storage for videos', function () {
|
||||
runTestSuite({
|
||||
maxUploadPart,
|
||||
playlistBucket: objectStorage.getMockBucketName('streaming-playlists'),
|
||||
webtorrentBucket: objectStorage.getMockBucketName('videos'),
|
||||
webVideoBucket: objectStorage.getMockBucketName('videos'),
|
||||
fixture
|
||||
})
|
||||
})
|
||||
|
||||
@@ -43,7 +43,7 @@ async function checkMagnetWebseeds (file: VideoFile, baseWebseeds: string[], ser
|
||||
}
|
||||
}
|
||||
|
||||
async function createServers (strategy: VideoRedundancyStrategy | null, additionalParams: any = {}, withWebtorrent = true) {
|
||||
async function createServers (strategy: VideoRedundancyStrategy | null, additionalParams: any = {}, withWebVideo = true) {
|
||||
const strategies: any[] = []
|
||||
|
||||
if (strategy !== null) {
|
||||
@@ -61,7 +61,7 @@ async function createServers (strategy: VideoRedundancyStrategy | null, addition
|
||||
const config = {
|
||||
transcoding: {
|
||||
webtorrent: {
|
||||
enabled: withWebtorrent
|
||||
enabled: withWebVideo
|
||||
},
|
||||
hls: {
|
||||
enabled: true
|
||||
@@ -100,7 +100,7 @@ async function createServers (strategy: VideoRedundancyStrategy | null, addition
|
||||
}
|
||||
|
||||
async function ensureSameFilenames (videoUUID: string) {
|
||||
let webtorrentFilenames: string[]
|
||||
let webVideoFilenames: string[]
|
||||
let hlsFilenames: string[]
|
||||
|
||||
for (const server of servers) {
|
||||
@@ -108,17 +108,17 @@ async function ensureSameFilenames (videoUUID: string) {
|
||||
|
||||
// Ensure we use the same filenames that the origin
|
||||
|
||||
const localWebtorrentFilenames = video.files.map(f => basename(f.fileUrl)).sort()
|
||||
const localWebVideoFilenames = video.files.map(f => basename(f.fileUrl)).sort()
|
||||
const localHLSFilenames = video.streamingPlaylists[0].files.map(f => basename(f.fileUrl)).sort()
|
||||
|
||||
if (webtorrentFilenames) expect(webtorrentFilenames).to.deep.equal(localWebtorrentFilenames)
|
||||
else webtorrentFilenames = localWebtorrentFilenames
|
||||
if (webVideoFilenames) expect(webVideoFilenames).to.deep.equal(localWebVideoFilenames)
|
||||
else webVideoFilenames = localWebVideoFilenames
|
||||
|
||||
if (hlsFilenames) expect(hlsFilenames).to.deep.equal(localHLSFilenames)
|
||||
else hlsFilenames = localHLSFilenames
|
||||
}
|
||||
|
||||
return { webtorrentFilenames, hlsFilenames }
|
||||
return { webVideoFilenames, hlsFilenames }
|
||||
}
|
||||
|
||||
async function check1WebSeed (videoUUID?: string) {
|
||||
@@ -156,7 +156,7 @@ async function check2Webseeds (videoUUID?: string) {
|
||||
}
|
||||
}
|
||||
|
||||
const { webtorrentFilenames } = await ensureSameFilenames(videoUUID)
|
||||
const { webVideoFilenames } = await ensureSameFilenames(videoUUID)
|
||||
|
||||
const directories = [
|
||||
servers[0].getDirectoryPath('redundancy'),
|
||||
@@ -168,7 +168,7 @@ async function check2Webseeds (videoUUID?: string) {
|
||||
expect(files).to.have.length.at.least(4)
|
||||
|
||||
// Ensure we files exist on disk
|
||||
expect(files.find(f => webtorrentFilenames.includes(f))).to.exist
|
||||
expect(files.find(f => webVideoFilenames.includes(f))).to.exist
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ import {
|
||||
describe('Test audio only video transcoding', function () {
|
||||
let servers: PeerTubeServer[] = []
|
||||
let videoUUID: string
|
||||
let webtorrentAudioFileUrl: string
|
||||
let webVideoAudioFileUrl: string
|
||||
let fragmentedAudioFileUrl: string
|
||||
|
||||
before(async function () {
|
||||
@@ -71,7 +71,7 @@ describe('Test audio only video transcoding', function () {
|
||||
}
|
||||
|
||||
if (server.serverNumber === 1) {
|
||||
webtorrentAudioFileUrl = video.files[2].fileUrl
|
||||
webVideoAudioFileUrl = video.files[2].fileUrl
|
||||
fragmentedAudioFileUrl = video.streamingPlaylists[0].files[2].fileUrl
|
||||
}
|
||||
}
|
||||
@@ -79,7 +79,7 @@ describe('Test audio only video transcoding', function () {
|
||||
|
||||
it('0p transcoded video should not have video', async function () {
|
||||
const paths = [
|
||||
servers[0].servers.buildWebTorrentFilePath(webtorrentAudioFileUrl),
|
||||
servers[0].servers.buildWebVideoFilePath(webVideoAudioFileUrl),
|
||||
servers[0].servers.buildFragmentedFilePath(videoUUID, fragmentedAudioFileUrl)
|
||||
]
|
||||
|
||||
|
||||
@@ -96,12 +96,12 @@ function runTests (enableObjectStorage: boolean) {
|
||||
}
|
||||
})
|
||||
|
||||
it('Should generate WebTorrent', async function () {
|
||||
it('Should generate Web Video', async function () {
|
||||
this.timeout(60000)
|
||||
|
||||
await servers[0].videos.runTranscoding({
|
||||
videoId: videoUUID,
|
||||
transcodingType: 'webtorrent'
|
||||
transcodingType: 'web-video'
|
||||
})
|
||||
|
||||
await waitJobs(servers)
|
||||
@@ -117,13 +117,13 @@ function runTests (enableObjectStorage: boolean) {
|
||||
}
|
||||
})
|
||||
|
||||
it('Should generate WebTorrent from HLS only video', async function () {
|
||||
it('Should generate Web Video from HLS only video', async function () {
|
||||
this.timeout(60000)
|
||||
|
||||
await servers[0].videos.removeAllWebTorrentFiles({ videoId: videoUUID })
|
||||
await servers[0].videos.removeAllWebVideoFiles({ videoId: videoUUID })
|
||||
await waitJobs(servers)
|
||||
|
||||
await servers[0].videos.runTranscoding({ videoId: videoUUID, transcodingType: 'webtorrent' })
|
||||
await servers[0].videos.runTranscoding({ videoId: videoUUID, transcodingType: 'web-video' })
|
||||
await waitJobs(servers)
|
||||
|
||||
for (const server of servers) {
|
||||
@@ -137,13 +137,13 @@ function runTests (enableObjectStorage: boolean) {
|
||||
}
|
||||
})
|
||||
|
||||
it('Should only generate WebTorrent', async function () {
|
||||
it('Should only generate Web Video', async function () {
|
||||
this.timeout(60000)
|
||||
|
||||
await servers[0].videos.removeHLSPlaylist({ videoId: videoUUID })
|
||||
await waitJobs(servers)
|
||||
|
||||
await servers[0].videos.runTranscoding({ videoId: videoUUID, transcodingType: 'webtorrent' })
|
||||
await servers[0].videos.runTranscoding({ videoId: videoUUID, transcodingType: 'web-video' })
|
||||
await waitJobs(servers)
|
||||
|
||||
for (const server of servers) {
|
||||
|
||||
@@ -111,7 +111,7 @@ describe('Test HLS videos', function () {
|
||||
await doubleFollow(servers[0], servers[1])
|
||||
})
|
||||
|
||||
describe('With WebTorrent & HLS enabled', function () {
|
||||
describe('With Web Video & HLS enabled', function () {
|
||||
runTestSuite(false)
|
||||
})
|
||||
|
||||
|
||||
@@ -251,7 +251,7 @@ describe('Test video transcoding', function () {
|
||||
expect(videoDetails.files).to.have.lengthOf(5)
|
||||
|
||||
const file = videoDetails.files.find(f => f.resolution.id === 240)
|
||||
const path = servers[1].servers.buildWebTorrentFilePath(file.fileUrl)
|
||||
const path = servers[1].servers.buildWebVideoFilePath(file.fileUrl)
|
||||
const probe = await getAudioStream(path)
|
||||
|
||||
if (probe.audioStream) {
|
||||
@@ -281,7 +281,7 @@ describe('Test video transcoding', function () {
|
||||
const videoDetails = await server.videos.get({ id: video.id })
|
||||
|
||||
const file = videoDetails.files.find(f => f.resolution.id === 240)
|
||||
const path = servers[1].servers.buildWebTorrentFilePath(file.fileUrl)
|
||||
const path = servers[1].servers.buildWebVideoFilePath(file.fileUrl)
|
||||
|
||||
expect(await hasAudioStream(path)).to.be.false
|
||||
}
|
||||
@@ -310,7 +310,7 @@ describe('Test video transcoding', function () {
|
||||
const fixtureVideoProbe = await getAudioStream(fixturePath)
|
||||
|
||||
const file = videoDetails.files.find(f => f.resolution.id === 240)
|
||||
const path = servers[1].servers.buildWebTorrentFilePath(file.fileUrl)
|
||||
const path = servers[1].servers.buildWebVideoFilePath(file.fileUrl)
|
||||
|
||||
const videoProbe = await getAudioStream(path)
|
||||
|
||||
@@ -472,14 +472,14 @@ describe('Test video transcoding', function () {
|
||||
|
||||
for (const resolution of [ 144, 240, 360, 480 ]) {
|
||||
const file = videoDetails.files.find(f => f.resolution.id === resolution)
|
||||
const path = servers[1].servers.buildWebTorrentFilePath(file.fileUrl)
|
||||
const path = servers[1].servers.buildWebVideoFilePath(file.fileUrl)
|
||||
const fps = await getVideoStreamFPS(path)
|
||||
|
||||
expect(fps).to.be.below(31)
|
||||
}
|
||||
|
||||
const file = videoDetails.files.find(f => f.resolution.id === 720)
|
||||
const path = servers[1].servers.buildWebTorrentFilePath(file.fileUrl)
|
||||
const path = servers[1].servers.buildWebVideoFilePath(file.fileUrl)
|
||||
const fps = await getVideoStreamFPS(path)
|
||||
|
||||
expect(fps).to.be.above(58).and.below(62)
|
||||
@@ -516,14 +516,14 @@ describe('Test video transcoding', function () {
|
||||
|
||||
{
|
||||
const file = video.files.find(f => f.resolution.id === 240)
|
||||
const path = servers[1].servers.buildWebTorrentFilePath(file.fileUrl)
|
||||
const path = servers[1].servers.buildWebVideoFilePath(file.fileUrl)
|
||||
const fps = await getVideoStreamFPS(path)
|
||||
expect(fps).to.be.equal(25)
|
||||
}
|
||||
|
||||
{
|
||||
const file = video.files.find(f => f.resolution.id === 720)
|
||||
const path = servers[1].servers.buildWebTorrentFilePath(file.fileUrl)
|
||||
const path = servers[1].servers.buildWebVideoFilePath(file.fileUrl)
|
||||
const fps = await getVideoStreamFPS(path)
|
||||
expect(fps).to.be.equal(59)
|
||||
}
|
||||
@@ -556,7 +556,7 @@ describe('Test video transcoding', function () {
|
||||
|
||||
for (const resolution of [ 240, 360, 480, 720, 1080 ]) {
|
||||
const file = video.files.find(f => f.resolution.id === resolution)
|
||||
const path = servers[1].servers.buildWebTorrentFilePath(file.fileUrl)
|
||||
const path = servers[1].servers.buildWebVideoFilePath(file.fileUrl)
|
||||
|
||||
const bitrate = await getVideoStreamBitrate(path)
|
||||
const fps = await getVideoStreamFPS(path)
|
||||
@@ -607,7 +607,7 @@ describe('Test video transcoding', function () {
|
||||
for (const r of resolutions) {
|
||||
const file = video.files.find(f => f.resolution.id === r)
|
||||
|
||||
const path = servers[1].servers.buildWebTorrentFilePath(file.fileUrl)
|
||||
const path = servers[1].servers.buildWebVideoFilePath(file.fileUrl)
|
||||
const bitrate = await getVideoStreamBitrate(path)
|
||||
|
||||
const inputBitrate = 60_000
|
||||
@@ -631,7 +631,7 @@ describe('Test video transcoding', function () {
|
||||
{
|
||||
const video = await servers[1].videos.get({ id: videoUUID })
|
||||
const file = video.files.find(f => f.resolution.id === 240)
|
||||
const path = servers[1].servers.buildWebTorrentFilePath(file.fileUrl)
|
||||
const path = servers[1].servers.buildWebVideoFilePath(file.fileUrl)
|
||||
|
||||
const probe = await ffprobePromise(path)
|
||||
const metadata = new VideoFileMetadata(probe)
|
||||
@@ -704,14 +704,14 @@ describe('Test video transcoding', function () {
|
||||
expect(transcodingJobs).to.have.lengthOf(16)
|
||||
|
||||
const hlsJobs = transcodingJobs.filter(j => j.data.type === 'new-resolution-to-hls')
|
||||
const webtorrentJobs = transcodingJobs.filter(j => j.data.type === 'new-resolution-to-webtorrent')
|
||||
const optimizeJobs = transcodingJobs.filter(j => j.data.type === 'optimize-to-webtorrent')
|
||||
const webVideoJobs = transcodingJobs.filter(j => j.data.type === 'new-resolution-to-web-video')
|
||||
const optimizeJobs = transcodingJobs.filter(j => j.data.type === 'optimize-to-web-video')
|
||||
|
||||
expect(hlsJobs).to.have.lengthOf(8)
|
||||
expect(webtorrentJobs).to.have.lengthOf(7)
|
||||
expect(webVideoJobs).to.have.lengthOf(7)
|
||||
expect(optimizeJobs).to.have.lengthOf(1)
|
||||
|
||||
for (const j of optimizeJobs.concat(hlsJobs.concat(webtorrentJobs))) {
|
||||
for (const j of optimizeJobs.concat(hlsJobs.concat(webVideoJobs))) {
|
||||
expect(j.priority).to.be.greaterThan(100)
|
||||
expect(j.priority).to.be.lessThan(150)
|
||||
}
|
||||
|
||||
@@ -96,7 +96,7 @@ describe('Test update video privacy while transcoding', function () {
|
||||
await doubleFollow(servers[0], servers[1])
|
||||
})
|
||||
|
||||
describe('With WebTorrent & HLS enabled', function () {
|
||||
describe('With Web Video & HLS enabled', function () {
|
||||
runTestSuite(false)
|
||||
})
|
||||
|
||||
|
||||
@@ -273,7 +273,7 @@ describe('Test video studio', function () {
|
||||
describe('HLS only studio edition', function () {
|
||||
|
||||
before(async function () {
|
||||
// Disable webtorrent
|
||||
// Disable Web Videos
|
||||
await servers[0].config.updateExistingSubConfig({
|
||||
newConfig: {
|
||||
transcoding: {
|
||||
@@ -354,8 +354,8 @@ describe('Test video studio', function () {
|
||||
expect(oldFileUrls).to.not.include(f.fileUrl)
|
||||
}
|
||||
|
||||
for (const webtorrentFile of video.files) {
|
||||
expectStartWith(webtorrentFile.fileUrl, objectStorage.getMockWebVideosBaseUrl())
|
||||
for (const webVideoFile of video.files) {
|
||||
expectStartWith(webVideoFile.fileUrl, objectStorage.getMockWebVideosBaseUrl())
|
||||
}
|
||||
|
||||
for (const hlsFile of video.streamingPlaylists[0].files) {
|
||||
|
||||
@@ -184,7 +184,7 @@ describe('Test user videos', function () {
|
||||
}
|
||||
})
|
||||
|
||||
it('Should disable webtorrent, enable HLS, and update my quota', async function () {
|
||||
it('Should disable web videos, enable HLS, and update my quota', async function () {
|
||||
this.timeout(160000)
|
||||
|
||||
{
|
||||
|
||||
@@ -229,25 +229,13 @@ describe('Test users', function () {
|
||||
})
|
||||
|
||||
it('Should be able to change the p2p attribute', async function () {
|
||||
{
|
||||
await server.users.updateMe({
|
||||
token: userToken,
|
||||
webTorrentEnabled: false
|
||||
})
|
||||
await server.users.updateMe({
|
||||
token: userToken,
|
||||
p2pEnabled: true
|
||||
})
|
||||
|
||||
const user = await server.users.getMyInfo({ token: userToken })
|
||||
expect(user.p2pEnabled).to.be.false
|
||||
}
|
||||
|
||||
{
|
||||
await server.users.updateMe({
|
||||
token: userToken,
|
||||
p2pEnabled: true
|
||||
})
|
||||
|
||||
const user = await server.users.getMyInfo({ token: userToken })
|
||||
expect(user.p2pEnabled).to.be.true
|
||||
}
|
||||
const user = await server.users.getMyInfo({ token: userToken })
|
||||
expect(user.p2pEnabled).to.be.true
|
||||
})
|
||||
|
||||
it('Should be able to change the email attribute', async function () {
|
||||
|
||||
@@ -48,10 +48,10 @@ describe('Test videos files', function () {
|
||||
await waitJobs(servers)
|
||||
})
|
||||
|
||||
it('Should delete webtorrent files', async function () {
|
||||
it('Should delete web video files', async function () {
|
||||
this.timeout(30_000)
|
||||
|
||||
await servers[0].videos.removeAllWebTorrentFiles({ videoId: validId1 })
|
||||
await servers[0].videos.removeAllWebVideoFiles({ videoId: validId1 })
|
||||
|
||||
await waitJobs(servers)
|
||||
|
||||
@@ -80,15 +80,15 @@ describe('Test videos files', function () {
|
||||
})
|
||||
|
||||
describe('When deleting a specific file', function () {
|
||||
let webtorrentId: string
|
||||
let webVideoId: string
|
||||
let hlsId: string
|
||||
|
||||
before(async function () {
|
||||
this.timeout(120_000)
|
||||
|
||||
{
|
||||
const { uuid } = await servers[0].videos.quickUpload({ name: 'webtorrent' })
|
||||
webtorrentId = uuid
|
||||
const { uuid } = await servers[0].videos.quickUpload({ name: 'web-video' })
|
||||
webVideoId = uuid
|
||||
}
|
||||
|
||||
{
|
||||
@@ -99,38 +99,38 @@ describe('Test videos files', function () {
|
||||
await waitJobs(servers)
|
||||
})
|
||||
|
||||
it('Shoulde delete a webtorrent file', async function () {
|
||||
it('Shoulde delete a web video file', async function () {
|
||||
this.timeout(30_000)
|
||||
|
||||
const video = await servers[0].videos.get({ id: webtorrentId })
|
||||
const video = await servers[0].videos.get({ id: webVideoId })
|
||||
const files = video.files
|
||||
|
||||
await servers[0].videos.removeWebTorrentFile({ videoId: webtorrentId, fileId: files[0].id })
|
||||
await servers[0].videos.removeWebVideoFile({ videoId: webVideoId, fileId: files[0].id })
|
||||
|
||||
await waitJobs(servers)
|
||||
|
||||
for (const server of servers) {
|
||||
const video = await server.videos.get({ id: webtorrentId })
|
||||
const video = await server.videos.get({ id: webVideoId })
|
||||
|
||||
expect(video.files).to.have.lengthOf(files.length - 1)
|
||||
expect(video.files.find(f => f.id === files[0].id)).to.not.exist
|
||||
}
|
||||
})
|
||||
|
||||
it('Should delete all webtorrent files', async function () {
|
||||
it('Should delete all web video files', async function () {
|
||||
this.timeout(30_000)
|
||||
|
||||
const video = await servers[0].videos.get({ id: webtorrentId })
|
||||
const video = await servers[0].videos.get({ id: webVideoId })
|
||||
const files = video.files
|
||||
|
||||
for (const file of files) {
|
||||
await servers[0].videos.removeWebTorrentFile({ videoId: webtorrentId, fileId: file.id })
|
||||
await servers[0].videos.removeWebVideoFile({ videoId: webVideoId, fileId: file.id })
|
||||
}
|
||||
|
||||
await waitJobs(servers)
|
||||
|
||||
for (const server of servers) {
|
||||
const video = await server.videos.get({ id: webtorrentId })
|
||||
const video = await server.videos.get({ id: webVideoId })
|
||||
|
||||
expect(video.files).to.have.lengthOf(0)
|
||||
}
|
||||
@@ -182,16 +182,16 @@ describe('Test videos files', function () {
|
||||
it('Should not delete last file of a video', async function () {
|
||||
this.timeout(60_000)
|
||||
|
||||
const webtorrentOnly = await servers[0].videos.get({ id: hlsId })
|
||||
const hlsOnly = await servers[0].videos.get({ id: webtorrentId })
|
||||
const webVideoOnly = await servers[0].videos.get({ id: hlsId })
|
||||
const hlsOnly = await servers[0].videos.get({ id: webVideoId })
|
||||
|
||||
for (let i = 0; i < 4; i++) {
|
||||
await servers[0].videos.removeWebTorrentFile({ videoId: webtorrentOnly.id, fileId: webtorrentOnly.files[i].id })
|
||||
await servers[0].videos.removeWebVideoFile({ videoId: webVideoOnly.id, fileId: webVideoOnly.files[i].id })
|
||||
await servers[0].videos.removeHLSFile({ videoId: hlsOnly.id, fileId: hlsOnly.streamingPlaylists[0].files[i].id })
|
||||
}
|
||||
|
||||
const expectedStatus = HttpStatusCode.BAD_REQUEST_400
|
||||
await servers[0].videos.removeWebTorrentFile({ videoId: webtorrentOnly.id, fileId: webtorrentOnly.files[4].id, expectedStatus })
|
||||
await servers[0].videos.removeWebVideoFile({ videoId: webVideoOnly.id, fileId: webVideoOnly.files[4].id, expectedStatus })
|
||||
await servers[0].videos.removeHLSFile({ videoId: hlsOnly.id, fileId: hlsOnly.streamingPlaylists[0].files[4].id, expectedStatus })
|
||||
})
|
||||
})
|
||||
|
||||
@@ -154,7 +154,7 @@ describe('Test videos filter', function () {
|
||||
server: PeerTubeServer
|
||||
path: string
|
||||
isLocal?: boolean
|
||||
hasWebtorrentFiles?: boolean
|
||||
hasWebVideoFiles?: boolean
|
||||
hasHLSFiles?: boolean
|
||||
include?: VideoInclude
|
||||
privacyOneOf?: VideoPrivacy[]
|
||||
@@ -174,7 +174,7 @@ describe('Test videos filter', function () {
|
||||
'include',
|
||||
'category',
|
||||
'tagsAllOf',
|
||||
'hasWebtorrentFiles',
|
||||
'hasWebVideoFiles',
|
||||
'hasHLSFiles',
|
||||
'privacyOneOf',
|
||||
'excludeAlreadyWatched'
|
||||
@@ -463,14 +463,14 @@ describe('Test videos filter', function () {
|
||||
}
|
||||
})
|
||||
|
||||
it('Should filter by HLS or WebTorrent files', async function () {
|
||||
it('Should filter by HLS or Web Video files', async function () {
|
||||
this.timeout(360000)
|
||||
|
||||
const finderFactory = (name: string) => (videos: Video[]) => videos.some(v => v.name === name)
|
||||
|
||||
await servers[0].config.enableTranscoding(true, false)
|
||||
await servers[0].videos.upload({ attributes: { name: 'webtorrent video' } })
|
||||
const hasWebtorrent = finderFactory('webtorrent video')
|
||||
await servers[0].videos.upload({ attributes: { name: 'web video video' } })
|
||||
const hasWebVideo = finderFactory('web video video')
|
||||
|
||||
await waitJobs(servers)
|
||||
|
||||
@@ -481,24 +481,24 @@ describe('Test videos filter', function () {
|
||||
await waitJobs(servers)
|
||||
|
||||
await servers[0].config.enableTranscoding(true, true)
|
||||
await servers[0].videos.upload({ attributes: { name: 'hls and webtorrent video' } })
|
||||
const hasBoth = finderFactory('hls and webtorrent video')
|
||||
await servers[0].videos.upload({ attributes: { name: 'hls and web video video' } })
|
||||
const hasBoth = finderFactory('hls and web video video')
|
||||
|
||||
await waitJobs(servers)
|
||||
|
||||
for (const path of paths) {
|
||||
{
|
||||
const videos = await listVideos({ server: servers[0], path, hasWebtorrentFiles: true })
|
||||
const videos = await listVideos({ server: servers[0], path, hasWebVideoFiles: true })
|
||||
|
||||
expect(hasWebtorrent(videos)).to.be.true
|
||||
expect(hasWebVideo(videos)).to.be.true
|
||||
expect(hasHLS(videos)).to.be.false
|
||||
expect(hasBoth(videos)).to.be.true
|
||||
}
|
||||
|
||||
{
|
||||
const videos = await listVideos({ server: servers[0], path, hasWebtorrentFiles: false })
|
||||
const videos = await listVideos({ server: servers[0], path, hasWebVideoFiles: false })
|
||||
|
||||
expect(hasWebtorrent(videos)).to.be.false
|
||||
expect(hasWebVideo(videos)).to.be.false
|
||||
expect(hasHLS(videos)).to.be.true
|
||||
expect(hasBoth(videos)).to.be.false
|
||||
}
|
||||
@@ -506,7 +506,7 @@ describe('Test videos filter', function () {
|
||||
{
|
||||
const videos = await listVideos({ server: servers[0], path, hasHLSFiles: true })
|
||||
|
||||
expect(hasWebtorrent(videos)).to.be.false
|
||||
expect(hasWebVideo(videos)).to.be.false
|
||||
expect(hasHLS(videos)).to.be.true
|
||||
expect(hasBoth(videos)).to.be.true
|
||||
}
|
||||
@@ -514,23 +514,23 @@ describe('Test videos filter', function () {
|
||||
{
|
||||
const videos = await listVideos({ server: servers[0], path, hasHLSFiles: false })
|
||||
|
||||
expect(hasWebtorrent(videos)).to.be.true
|
||||
expect(hasWebVideo(videos)).to.be.true
|
||||
expect(hasHLS(videos)).to.be.false
|
||||
expect(hasBoth(videos)).to.be.false
|
||||
}
|
||||
|
||||
{
|
||||
const videos = await listVideos({ server: servers[0], path, hasHLSFiles: false, hasWebtorrentFiles: false })
|
||||
const videos = await listVideos({ server: servers[0], path, hasHLSFiles: false, hasWebVideoFiles: false })
|
||||
|
||||
expect(hasWebtorrent(videos)).to.be.false
|
||||
expect(hasWebVideo(videos)).to.be.false
|
||||
expect(hasHLS(videos)).to.be.false
|
||||
expect(hasBoth(videos)).to.be.false
|
||||
}
|
||||
|
||||
{
|
||||
const videos = await listVideos({ server: servers[0], path, hasHLSFiles: true, hasWebtorrentFiles: true })
|
||||
const videos = await listVideos({ server: servers[0], path, hasHLSFiles: true, hasWebVideoFiles: true })
|
||||
|
||||
expect(hasWebtorrent(videos)).to.be.false
|
||||
expect(hasWebVideo(videos)).to.be.false
|
||||
expect(hasHLS(videos)).to.be.false
|
||||
expect(hasBoth(videos)).to.be.true
|
||||
}
|
||||
|
||||
@@ -44,8 +44,8 @@ describe('Test studio transcoding in peertube-runner program', function () {
|
||||
}
|
||||
|
||||
if (objectStorage) {
|
||||
for (const webtorrentFile of video.files) {
|
||||
expectStartWith(webtorrentFile.fileUrl, objectStorage.getMockWebVideosBaseUrl())
|
||||
for (const webVideoFile of video.files) {
|
||||
expectStartWith(webVideoFile.fileUrl, objectStorage.getMockWebVideosBaseUrl())
|
||||
}
|
||||
|
||||
for (const hlsFile of video.streamingPlaylists[0].files) {
|
||||
|
||||
@@ -24,13 +24,13 @@ describe('Test VOD transcoding in peertube-runner program', function () {
|
||||
let peertubeRunner: PeerTubeRunnerProcess
|
||||
|
||||
function runSuite (options: {
|
||||
webtorrentEnabled: boolean
|
||||
webVideoEnabled: boolean
|
||||
hlsEnabled: boolean
|
||||
objectStorage?: ObjectStorageCommand
|
||||
}) {
|
||||
const { webtorrentEnabled, hlsEnabled, objectStorage } = options
|
||||
const { webVideoEnabled, hlsEnabled, objectStorage } = options
|
||||
|
||||
const objectStorageBaseUrlWebTorrent = objectStorage
|
||||
const objectStorageBaseUrlWebVideo = objectStorage
|
||||
? objectStorage.getMockWebVideosBaseUrl()
|
||||
: undefined
|
||||
|
||||
@@ -46,13 +46,13 @@ describe('Test VOD transcoding in peertube-runner program', function () {
|
||||
await waitJobs(servers, { runnerJobs: true })
|
||||
|
||||
for (const server of servers) {
|
||||
if (webtorrentEnabled) {
|
||||
if (webVideoEnabled) {
|
||||
await completeWebVideoFilesCheck({
|
||||
server,
|
||||
originServer: servers[0],
|
||||
fixture: 'video_short.mp4',
|
||||
videoUUID: uuid,
|
||||
objectStorageBaseUrl: objectStorageBaseUrlWebTorrent,
|
||||
objectStorageBaseUrl: objectStorageBaseUrlWebVideo,
|
||||
files: [
|
||||
{ resolution: 0 },
|
||||
{ resolution: 144 },
|
||||
@@ -66,7 +66,7 @@ describe('Test VOD transcoding in peertube-runner program', function () {
|
||||
|
||||
if (hlsEnabled) {
|
||||
await completeCheckHlsPlaylist({
|
||||
hlsOnly: !webtorrentEnabled,
|
||||
hlsOnly: !webVideoEnabled,
|
||||
servers,
|
||||
videoUUID: uuid,
|
||||
objectStorageBaseUrl: objectStorageBaseUrlHLS,
|
||||
@@ -84,13 +84,13 @@ describe('Test VOD transcoding in peertube-runner program', function () {
|
||||
await waitJobs(servers, { runnerJobs: true })
|
||||
|
||||
for (const server of servers) {
|
||||
if (webtorrentEnabled) {
|
||||
if (webVideoEnabled) {
|
||||
await completeWebVideoFilesCheck({
|
||||
server,
|
||||
originServer: servers[0],
|
||||
fixture: 'video_short.webm',
|
||||
videoUUID: uuid,
|
||||
objectStorageBaseUrl: objectStorageBaseUrlWebTorrent,
|
||||
objectStorageBaseUrl: objectStorageBaseUrlWebVideo,
|
||||
files: [
|
||||
{ resolution: 0 },
|
||||
{ resolution: 144 },
|
||||
@@ -104,7 +104,7 @@ describe('Test VOD transcoding in peertube-runner program', function () {
|
||||
|
||||
if (hlsEnabled) {
|
||||
await completeCheckHlsPlaylist({
|
||||
hlsOnly: !webtorrentEnabled,
|
||||
hlsOnly: !webVideoEnabled,
|
||||
servers,
|
||||
videoUUID: uuid,
|
||||
objectStorageBaseUrl: objectStorageBaseUrlHLS,
|
||||
@@ -123,13 +123,13 @@ describe('Test VOD transcoding in peertube-runner program', function () {
|
||||
await waitJobs(servers, { runnerJobs: true })
|
||||
|
||||
for (const server of servers) {
|
||||
if (webtorrentEnabled) {
|
||||
if (webVideoEnabled) {
|
||||
await completeWebVideoFilesCheck({
|
||||
server,
|
||||
originServer: servers[0],
|
||||
fixture: 'sample.ogg',
|
||||
videoUUID: uuid,
|
||||
objectStorageBaseUrl: objectStorageBaseUrlWebTorrent,
|
||||
objectStorageBaseUrl: objectStorageBaseUrlWebVideo,
|
||||
files: [
|
||||
{ resolution: 0 },
|
||||
{ resolution: 144 },
|
||||
@@ -142,7 +142,7 @@ describe('Test VOD transcoding in peertube-runner program', function () {
|
||||
|
||||
if (hlsEnabled) {
|
||||
await completeCheckHlsPlaylist({
|
||||
hlsOnly: !webtorrentEnabled,
|
||||
hlsOnly: !webVideoEnabled,
|
||||
servers,
|
||||
videoUUID: uuid,
|
||||
objectStorageBaseUrl: objectStorageBaseUrlHLS,
|
||||
@@ -159,13 +159,13 @@ describe('Test VOD transcoding in peertube-runner program', function () {
|
||||
|
||||
await waitJobs(servers, { runnerJobs: true })
|
||||
|
||||
if (webtorrentEnabled) {
|
||||
if (webVideoEnabled) {
|
||||
await completeWebVideoFilesCheck({
|
||||
server: servers[0],
|
||||
originServer: servers[0],
|
||||
fixture: 'video_short.mp4',
|
||||
videoUUID: uuid,
|
||||
objectStorageBaseUrl: objectStorageBaseUrlWebTorrent,
|
||||
objectStorageBaseUrl: objectStorageBaseUrlWebVideo,
|
||||
files: [
|
||||
{ resolution: 0 },
|
||||
{ resolution: 144 },
|
||||
@@ -179,7 +179,7 @@ describe('Test VOD transcoding in peertube-runner program', function () {
|
||||
|
||||
if (hlsEnabled) {
|
||||
await completeCheckHlsPlaylist({
|
||||
hlsOnly: !webtorrentEnabled,
|
||||
hlsOnly: !webVideoEnabled,
|
||||
servers: [ servers[0] ],
|
||||
videoUUID: uuid,
|
||||
objectStorageBaseUrl: objectStorageBaseUrlHLS,
|
||||
@@ -203,7 +203,7 @@ describe('Test VOD transcoding in peertube-runner program', function () {
|
||||
|
||||
await servers[0].config.enableTranscoding(true, true, true)
|
||||
|
||||
await servers[0].videos.runTranscoding({ transcodingType: 'webtorrent', videoId: uuid })
|
||||
await servers[0].videos.runTranscoding({ transcodingType: 'web-video', videoId: uuid })
|
||||
await waitJobs(servers, { runnerJobs: true })
|
||||
|
||||
await completeWebVideoFilesCheck({
|
||||
@@ -211,7 +211,7 @@ describe('Test VOD transcoding in peertube-runner program', function () {
|
||||
originServer: servers[0],
|
||||
fixture: 'video_short.mp4',
|
||||
videoUUID: uuid,
|
||||
objectStorageBaseUrl: objectStorageBaseUrlWebTorrent,
|
||||
objectStorageBaseUrl: objectStorageBaseUrlWebVideo,
|
||||
files: [
|
||||
{ resolution: 0 },
|
||||
{ resolution: 144 },
|
||||
@@ -262,7 +262,7 @@ describe('Test VOD transcoding in peertube-runner program', function () {
|
||||
await servers[0].config.enableTranscoding(true, false, true)
|
||||
})
|
||||
|
||||
runSuite({ webtorrentEnabled: true, hlsEnabled: false })
|
||||
runSuite({ webVideoEnabled: true, hlsEnabled: false })
|
||||
})
|
||||
|
||||
describe('HLS videos only enabled', function () {
|
||||
@@ -271,7 +271,7 @@ describe('Test VOD transcoding in peertube-runner program', function () {
|
||||
await servers[0].config.enableTranscoding(false, true, true)
|
||||
})
|
||||
|
||||
runSuite({ webtorrentEnabled: false, hlsEnabled: true })
|
||||
runSuite({ webVideoEnabled: false, hlsEnabled: true })
|
||||
})
|
||||
|
||||
describe('Web video & HLS enabled', function () {
|
||||
@@ -280,7 +280,7 @@ describe('Test VOD transcoding in peertube-runner program', function () {
|
||||
await servers[0].config.enableTranscoding(true, true, true)
|
||||
})
|
||||
|
||||
runSuite({ webtorrentEnabled: true, hlsEnabled: true })
|
||||
runSuite({ webVideoEnabled: true, hlsEnabled: true })
|
||||
})
|
||||
})
|
||||
|
||||
@@ -306,7 +306,7 @@ describe('Test VOD transcoding in peertube-runner program', function () {
|
||||
await servers[0].config.enableTranscoding(true, false, true)
|
||||
})
|
||||
|
||||
runSuite({ webtorrentEnabled: true, hlsEnabled: false, objectStorage })
|
||||
runSuite({ webVideoEnabled: true, hlsEnabled: false, objectStorage })
|
||||
})
|
||||
|
||||
describe('HLS videos only enabled', function () {
|
||||
@@ -315,7 +315,7 @@ describe('Test VOD transcoding in peertube-runner program', function () {
|
||||
await servers[0].config.enableTranscoding(false, true, true)
|
||||
})
|
||||
|
||||
runSuite({ webtorrentEnabled: false, hlsEnabled: true, objectStorage })
|
||||
runSuite({ webVideoEnabled: false, hlsEnabled: true, objectStorage })
|
||||
})
|
||||
|
||||
describe('Web video & HLS enabled', function () {
|
||||
@@ -324,7 +324,7 @@ describe('Test VOD transcoding in peertube-runner program', function () {
|
||||
await servers[0].config.enableTranscoding(true, true, true)
|
||||
})
|
||||
|
||||
runSuite({ webtorrentEnabled: true, hlsEnabled: true, objectStorage })
|
||||
runSuite({ webVideoEnabled: true, hlsEnabled: true, objectStorage })
|
||||
})
|
||||
|
||||
after(async function () {
|
||||
|
||||
@@ -302,11 +302,11 @@ describe('Test plugin helpers', function () {
|
||||
|
||||
// Video files check
|
||||
{
|
||||
expect(body.webtorrent.videoFiles).to.be.an('array')
|
||||
expect(body.webVideo.videoFiles).to.be.an('array')
|
||||
expect(body.hls.videoFiles).to.be.an('array')
|
||||
|
||||
for (const resolution of [ 144, 240, 360, 480, 720 ]) {
|
||||
for (const files of [ body.webtorrent.videoFiles, body.hls.videoFiles ]) {
|
||||
for (const files of [ body.webVideo.videoFiles, body.hls.videoFiles ]) {
|
||||
const file = files.find(f => f.resolution === resolution)
|
||||
expect(file).to.exist
|
||||
|
||||
@@ -318,7 +318,7 @@ describe('Test plugin helpers', function () {
|
||||
}
|
||||
}
|
||||
|
||||
videoPath = body.webtorrent.videoFiles[0].path
|
||||
videoPath = body.webVideo.videoFiles[0].path
|
||||
}
|
||||
|
||||
// Thumbnails check
|
||||
|
||||
@@ -247,7 +247,7 @@ describe('Test transcoding plugins', function () {
|
||||
|
||||
const video = await server.videos.get({ id: videoUUID })
|
||||
|
||||
const path = server.servers.buildWebTorrentFilePath(video.files[0].fileUrl)
|
||||
const path = server.servers.buildWebVideoFilePath(video.files[0].fileUrl)
|
||||
const audioProbe = await getAudioStream(path)
|
||||
expect(audioProbe.audioStream.codec_name).to.equal('opus')
|
||||
|
||||
|
||||
@@ -215,22 +215,22 @@ async function checkVideoFilesWereRemoved (options: {
|
||||
}) {
|
||||
const { video, server, captions = [], onlyVideoFiles = false } = options
|
||||
|
||||
const webtorrentFiles = video.files || []
|
||||
const webVideoFiles = video.files || []
|
||||
const hlsFiles = video.streamingPlaylists[0]?.files || []
|
||||
|
||||
const thumbnailName = basename(video.thumbnailPath)
|
||||
const previewName = basename(video.previewPath)
|
||||
|
||||
const torrentNames = webtorrentFiles.concat(hlsFiles).map(f => basename(f.torrentUrl))
|
||||
const torrentNames = webVideoFiles.concat(hlsFiles).map(f => basename(f.torrentUrl))
|
||||
|
||||
const captionNames = captions.map(c => basename(c.captionPath))
|
||||
|
||||
const webtorrentFilenames = webtorrentFiles.map(f => basename(f.fileUrl))
|
||||
const webVideoFilenames = webVideoFiles.map(f => basename(f.fileUrl))
|
||||
const hlsFilenames = hlsFiles.map(f => basename(f.fileUrl))
|
||||
|
||||
let directories: { [ directory: string ]: string[] } = {
|
||||
videos: webtorrentFilenames,
|
||||
redundancy: webtorrentFilenames,
|
||||
videos: webVideoFilenames,
|
||||
redundancy: webVideoFilenames,
|
||||
[join('playlists', 'hls')]: hlsFilenames,
|
||||
[join('redundancy', 'hls')]: hlsFilenames
|
||||
}
|
||||
|
||||
@@ -65,19 +65,19 @@ async function listRedundanciesCLI (target: VideoRedundanciesTarget) {
|
||||
}) as any
|
||||
|
||||
for (const redundancy of data) {
|
||||
const webtorrentFiles = redundancy.redundancies.files
|
||||
const webVideoFiles = redundancy.redundancies.files
|
||||
const streamingPlaylists = redundancy.redundancies.streamingPlaylists
|
||||
|
||||
let totalSize = ''
|
||||
if (target === 'remote-videos') {
|
||||
const tmp = webtorrentFiles.concat(streamingPlaylists)
|
||||
const tmp = webVideoFiles.concat(streamingPlaylists)
|
||||
.reduce((a, b) => a + b.size, 0)
|
||||
|
||||
totalSize = bytes(tmp)
|
||||
}
|
||||
|
||||
const instances = uniqify(
|
||||
webtorrentFiles.concat(streamingPlaylists)
|
||||
webVideoFiles.concat(streamingPlaylists)
|
||||
.map(r => r.fileUrl)
|
||||
.map(u => new URL(u).host)
|
||||
)
|
||||
@@ -86,7 +86,7 @@ async function listRedundanciesCLI (target: VideoRedundanciesTarget) {
|
||||
redundancy.id.toString(),
|
||||
redundancy.name,
|
||||
redundancy.url,
|
||||
webtorrentFiles.length,
|
||||
webVideoFiles.length,
|
||||
streamingPlaylists.length,
|
||||
instances.join('\n'),
|
||||
totalSize
|
||||
|
||||
@@ -38,6 +38,6 @@ export function isStreamingPlaylistFile (file: any): file is MVideoFileStreaming
|
||||
return !!file.videoStreamingPlaylistId
|
||||
}
|
||||
|
||||
export function isWebtorrentFile (file: any): file is MVideoFileVideo {
|
||||
export function isWebVideoFile (file: any): file is MVideoFileVideo {
|
||||
return !!file.videoId
|
||||
}
|
||||
|
||||
@@ -41,7 +41,17 @@ export type PeerTubeHelpers = {
|
||||
ffprobe: (path: string) => Promise<any>
|
||||
|
||||
getFiles: (id: number | string) => Promise<{
|
||||
webtorrent: {
|
||||
webtorrent: { // TODO: remove in v7
|
||||
videoFiles: {
|
||||
path: string // Could be null if using remote storage
|
||||
url: string
|
||||
resolution: number
|
||||
size: number
|
||||
fps: number
|
||||
}[]
|
||||
}
|
||||
|
||||
webVideo: {
|
||||
videoFiles: {
|
||||
path: string // Could be null if using remote storage
|
||||
url: string
|
||||
|
||||
Reference in New Issue
Block a user