mirror of https://github.com/Chocobozzz/PeerTube
Update torrent metadata on video update
parent
a23f6c94ed
commit
9b293cd6a2
|
@ -17,7 +17,7 @@ import { VideoCommentModel } from '../server/models/video/video-comment'
|
||||||
import { AccountModel } from '../server/models/account/account'
|
import { AccountModel } from '../server/models/account/account'
|
||||||
import { VideoChannelModel } from '../server/models/video/video-channel'
|
import { VideoChannelModel } from '../server/models/video/video-channel'
|
||||||
import { initDatabaseModels } from '../server/initializers/database'
|
import { initDatabaseModels } from '../server/initializers/database'
|
||||||
import { updateTorrentUrls } from '@server/helpers/webtorrent'
|
import { updateTorrentMetadata } from '@server/helpers/webtorrent'
|
||||||
import { getServerActor } from '@server/models/application/application'
|
import { getServerActor } from '@server/models/application/application'
|
||||||
|
|
||||||
run()
|
run()
|
||||||
|
@ -126,7 +126,7 @@ async function run () {
|
||||||
|
|
||||||
for (const file of video.VideoFiles) {
|
for (const file of video.VideoFiles) {
|
||||||
console.log('Updating torrent file %s of video %s.', file.resolution, video.uuid)
|
console.log('Updating torrent file %s of video %s.', file.resolution, video.uuid)
|
||||||
await updateTorrentUrls(video, file)
|
await updateTorrentMetadata(video, file)
|
||||||
|
|
||||||
await file.save()
|
await file.save()
|
||||||
}
|
}
|
||||||
|
@ -135,7 +135,7 @@ async function run () {
|
||||||
for (const file of (playlist?.VideoFiles || [])) {
|
for (const file of (playlist?.VideoFiles || [])) {
|
||||||
console.log('Updating fragmented torrent file %s of video %s.', file.resolution, video.uuid)
|
console.log('Updating fragmented torrent file %s of video %s.', file.resolution, video.uuid)
|
||||||
|
|
||||||
await updateTorrentUrls(video, file)
|
await updateTorrentMetadata(video, file)
|
||||||
|
|
||||||
await file.save()
|
await file.save()
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import express from 'express'
|
import express from 'express'
|
||||||
import { Transaction } from 'sequelize/types'
|
import { Transaction } from 'sequelize/types'
|
||||||
|
import { updateTorrentMetadata } from '@server/helpers/webtorrent'
|
||||||
import { changeVideoChannelShare } from '@server/lib/activitypub/share'
|
import { changeVideoChannelShare } from '@server/lib/activitypub/share'
|
||||||
import { buildVideoThumbnailsFromReq, setVideoTags } from '@server/lib/video'
|
import { buildVideoThumbnailsFromReq, setVideoTags } from '@server/lib/video'
|
||||||
import { openapiOperationDoc } from '@server/middlewares/doc'
|
import { openapiOperationDoc } from '@server/middlewares/doc'
|
||||||
|
@ -149,9 +150,8 @@ async function updateVideo (req: express.Request, res: express.Response) {
|
||||||
return videoInstanceUpdated
|
return videoInstanceUpdated
|
||||||
})
|
})
|
||||||
|
|
||||||
if (wasConfidentialVideo) {
|
if (videoInfoToUpdate.name) await updateTorrentsMetadata(videoInstanceUpdated)
|
||||||
Notifier.Instance.notifyOnNewVideoIfNeeded(videoInstanceUpdated)
|
if (wasConfidentialVideo) Notifier.Instance.notifyOnNewVideoIfNeeded(videoInstanceUpdated)
|
||||||
}
|
|
||||||
|
|
||||||
Hooks.runAction('action:api.video.updated', { video: videoInstanceUpdated, body: req.body, req, res })
|
Hooks.runAction('action:api.video.updated', { video: videoInstanceUpdated, body: req.body, req, res })
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
@ -199,3 +199,9 @@ function updateSchedule (videoInstance: MVideoFullLight, videoInfoToUpdate: Vide
|
||||||
return ScheduleVideoUpdateModel.deleteByVideoId(videoInstance.id, transaction)
|
return ScheduleVideoUpdateModel.deleteByVideoId(videoInstance.id, transaction)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function updateTorrentsMetadata (video: MVideoFullLight) {
|
||||||
|
for (const file of video.getAllFiles()) {
|
||||||
|
await updateTorrentMetadata(video, file)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -94,7 +94,7 @@ function createTorrentAndSetInfoHash (videoOrPlaylist: MVideo | MStreamingPlayli
|
||||||
|
|
||||||
const options = {
|
const options = {
|
||||||
// Keep the extname, it's used by the client to stream the file inside a web browser
|
// Keep the extname, it's used by the client to stream the file inside a web browser
|
||||||
name: `${video.name} ${videoFile.resolution}p${videoFile.extname}`,
|
name: buildInfoName(video, videoFile),
|
||||||
createdBy: 'PeerTube',
|
createdBy: 'PeerTube',
|
||||||
announceList: buildAnnounceList(),
|
announceList: buildAnnounceList(),
|
||||||
urlList: buildUrlList(video, videoFile)
|
urlList: buildUrlList(video, videoFile)
|
||||||
|
@ -120,7 +120,7 @@ function createTorrentAndSetInfoHash (videoOrPlaylist: MVideo | MStreamingPlayli
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
async function updateTorrentUrls (videoOrPlaylist: MVideo | MStreamingPlaylistVideo, videoFile: MVideoFile) {
|
async function updateTorrentMetadata (videoOrPlaylist: MVideo | MStreamingPlaylistVideo, videoFile: MVideoFile) {
|
||||||
const video = extractVideo(videoOrPlaylist)
|
const video = extractVideo(videoOrPlaylist)
|
||||||
|
|
||||||
const oldTorrentPath = join(CONFIG.STORAGE.TORRENTS_DIR, videoFile.torrentFilename)
|
const oldTorrentPath = join(CONFIG.STORAGE.TORRENTS_DIR, videoFile.torrentFilename)
|
||||||
|
@ -133,10 +133,13 @@ async function updateTorrentUrls (videoOrPlaylist: MVideo | MStreamingPlaylistVi
|
||||||
|
|
||||||
decoded['url-list'] = buildUrlList(video, videoFile)
|
decoded['url-list'] = buildUrlList(video, videoFile)
|
||||||
|
|
||||||
|
decoded.info.name = buildInfoName(video, videoFile)
|
||||||
|
decoded['creation date'] = Math.ceil(Date.now() / 1000)
|
||||||
|
|
||||||
const newTorrentFilename = generateTorrentFileName(videoOrPlaylist, videoFile.resolution)
|
const newTorrentFilename = generateTorrentFileName(videoOrPlaylist, videoFile.resolution)
|
||||||
const newTorrentPath = join(CONFIG.STORAGE.TORRENTS_DIR, newTorrentFilename)
|
const newTorrentPath = join(CONFIG.STORAGE.TORRENTS_DIR, newTorrentFilename)
|
||||||
|
|
||||||
logger.info('Updating torrent URLs %s -> %s.', oldTorrentPath, newTorrentPath)
|
logger.info('Updating torrent metadata %s -> %s.', oldTorrentPath, newTorrentPath)
|
||||||
|
|
||||||
await writeFile(newTorrentPath, encode(decoded))
|
await writeFile(newTorrentPath, encode(decoded))
|
||||||
await remove(join(CONFIG.STORAGE.TORRENTS_DIR, videoFile.torrentFilename))
|
await remove(join(CONFIG.STORAGE.TORRENTS_DIR, videoFile.torrentFilename))
|
||||||
|
@ -171,7 +174,7 @@ function generateMagnetUri (
|
||||||
|
|
||||||
export {
|
export {
|
||||||
createTorrentPromise,
|
createTorrentPromise,
|
||||||
updateTorrentUrls,
|
updateTorrentMetadata,
|
||||||
createTorrentAndSetInfoHash,
|
createTorrentAndSetInfoHash,
|
||||||
generateMagnetUri,
|
generateMagnetUri,
|
||||||
downloadWebTorrentVideo
|
downloadWebTorrentVideo
|
||||||
|
@ -226,3 +229,7 @@ function buildAnnounceList () {
|
||||||
function buildUrlList (video: MVideo, videoFile: MVideoFile) {
|
function buildUrlList (video: MVideo, videoFile: MVideoFile) {
|
||||||
return [ videoFile.getFileUrl(video) ]
|
return [ videoFile.getFileUrl(video) ]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function buildInfoName (video: MVideo, videoFile: MVideoFile) {
|
||||||
|
return `${video.name} ${videoFile.resolution}p${videoFile.extname}`
|
||||||
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@ import { Job } from 'bull'
|
||||||
import { remove } from 'fs-extra'
|
import { remove } from 'fs-extra'
|
||||||
import { join } from 'path'
|
import { join } from 'path'
|
||||||
import { logger } from '@server/helpers/logger'
|
import { logger } from '@server/helpers/logger'
|
||||||
import { updateTorrentUrls } from '@server/helpers/webtorrent'
|
import { updateTorrentMetadata } from '@server/helpers/webtorrent'
|
||||||
import { CONFIG } from '@server/initializers/config'
|
import { CONFIG } from '@server/initializers/config'
|
||||||
import { P2P_MEDIA_LOADER_PEER_VERSION } from '@server/initializers/constants'
|
import { P2P_MEDIA_LOADER_PEER_VERSION } from '@server/initializers/constants'
|
||||||
import { storeHLSFile, storeWebTorrentFile } from '@server/lib/object-storage'
|
import { storeHLSFile, storeWebTorrentFile } from '@server/lib/object-storage'
|
||||||
|
@ -113,7 +113,7 @@ async function onFileMoved (options: {
|
||||||
file.fileUrl = fileUrl
|
file.fileUrl = fileUrl
|
||||||
file.storage = VideoStorage.OBJECT_STORAGE
|
file.storage = VideoStorage.OBJECT_STORAGE
|
||||||
|
|
||||||
await updateTorrentUrls(videoOrPlaylist, file)
|
await updateTorrentMetadata(videoOrPlaylist, file)
|
||||||
await file.save()
|
await file.save()
|
||||||
|
|
||||||
logger.debug('Removing %s because it\'s now on object storage', oldPath)
|
logger.debug('Removing %s because it\'s now on object storage', oldPath)
|
||||||
|
|
|
@ -276,7 +276,7 @@ export class VideoPlaylistElementModel extends Model<Partial<AttributesOnly<Vide
|
||||||
}
|
}
|
||||||
|
|
||||||
const positionQuery = Sequelize.literal(`${newPosition} + "position" - ${firstPosition}`)
|
const positionQuery = Sequelize.literal(`${newPosition} + "position" - ${firstPosition}`)
|
||||||
return VideoPlaylistElementModel.update({ position: positionQuery as any }, query)
|
return VideoPlaylistElementModel.update({ position: positionQuery }, query)
|
||||||
}
|
}
|
||||||
|
|
||||||
static increasePositionOf (
|
static increasePositionOf (
|
||||||
|
|
|
@ -1539,6 +1539,21 @@ export class VideoModel extends Model<Partial<AttributesOnly<VideoModel>>> {
|
||||||
return this.VideoChannel.Account.Actor.Server?.isBlocked() || this.VideoChannel.Account.isBlocked()
|
return this.VideoChannel.Account.Actor.Server?.isBlocked() || this.VideoChannel.Account.isBlocked()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getAllFiles () {
|
||||||
|
let files: MVideoFile[] = []
|
||||||
|
|
||||||
|
if (Array.isArray(this.VideoFiles)) {
|
||||||
|
files = files.concat(this.VideoFiles)
|
||||||
|
}
|
||||||
|
|
||||||
|
const hls = this.getHLSPlaylist()
|
||||||
|
if (hls) {
|
||||||
|
files = files.concat(hls.VideoFiles)
|
||||||
|
}
|
||||||
|
|
||||||
|
return files
|
||||||
|
}
|
||||||
|
|
||||||
getQualityFileBy<T extends MVideoWithFile> (this: T, fun: (files: MVideoFile[], it: (file: MVideoFile) => number) => MVideoFile) {
|
getQualityFileBy<T extends MVideoWithFile> (this: T, fun: (files: MVideoFile[], it: (file: MVideoFile) => number) => MVideoFile) {
|
||||||
// We first transcode to WebTorrent format, so try this array first
|
// We first transcode to WebTorrent format, so try this array first
|
||||||
if (Array.isArray(this.VideoFiles) && this.VideoFiles.length !== 0) {
|
if (Array.isArray(this.VideoFiles) && this.VideoFiles.length !== 0) {
|
||||||
|
|
|
@ -217,6 +217,7 @@ async function completeVideoCheck (
|
||||||
expect(torrent.files).to.be.an('array')
|
expect(torrent.files).to.be.an('array')
|
||||||
expect(torrent.files.length).to.equal(1)
|
expect(torrent.files.length).to.equal(1)
|
||||||
expect(torrent.files[0].path).to.exist.and.to.not.equal('')
|
expect(torrent.files[0].path).to.exist.and.to.not.equal('')
|
||||||
|
expect(torrent.files[0].name).to.equal(`${videoDetails.name} ${file.resolution.id}p${extension}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
expect(videoDetails.thumbnailPath).to.exist
|
expect(videoDetails.thumbnailPath).to.exist
|
||||||
|
|
Loading…
Reference in New Issue