diff options
author | Chocobozzz <me@florianbigard.com> | 2021-07-23 11:20:00 +0200 |
---|---|---|
committer | Chocobozzz <chocobozzz@cpy.re> | 2021-07-26 11:29:31 +0200 |
commit | 764b1a14fc494f2cfd7ea590d2f07b01df65c7ad (patch) | |
tree | 198ca5f242c63a205a05fa4cfd6d063277c541fd /scripts | |
parent | 83903cb65d531a6b6b91715387493ba8312b264d (diff) | |
download | PeerTube-764b1a14fc494f2cfd7ea590d2f07b01df65c7ad.tar.gz PeerTube-764b1a14fc494f2cfd7ea590d2f07b01df65c7ad.tar.zst PeerTube-764b1a14fc494f2cfd7ea590d2f07b01df65c7ad.zip |
Use random names for VOD HLS playlists
Diffstat (limited to 'scripts')
-rw-r--r-- | scripts/optimize-old-videos.ts | 32 | ||||
-rwxr-xr-x | scripts/prune-storage.ts | 62 | ||||
-rwxr-xr-x | scripts/update-host.ts | 13 |
3 files changed, 52 insertions, 55 deletions
diff --git a/scripts/optimize-old-videos.ts b/scripts/optimize-old-videos.ts index 9692d76ba..bde9d1e01 100644 --- a/scripts/optimize-old-videos.ts +++ b/scripts/optimize-old-videos.ts | |||
@@ -19,13 +19,13 @@ run() | |||
19 | process.exit(-1) | 19 | process.exit(-1) |
20 | }) | 20 | }) |
21 | 21 | ||
22 | let currentVideoId = null | 22 | let currentVideoId: string |
23 | let currentFile = null | 23 | let currentFilePath: string |
24 | 24 | ||
25 | process.on('SIGINT', async function () { | 25 | process.on('SIGINT', async function () { |
26 | console.log('Cleaning up temp files') | 26 | console.log('Cleaning up temp files') |
27 | await remove(`${currentFile}_backup`) | 27 | await remove(`${currentFilePath}_backup`) |
28 | await remove(`${dirname(currentFile)}/${currentVideoId}-transcoded.mp4`) | 28 | await remove(`${dirname(currentFilePath)}/${currentVideoId}-transcoded.mp4`) |
29 | process.exit(0) | 29 | process.exit(0) |
30 | }) | 30 | }) |
31 | 31 | ||
@@ -40,12 +40,12 @@ async function run () { | |||
40 | currentVideoId = video.id | 40 | currentVideoId = video.id |
41 | 41 | ||
42 | for (const file of video.VideoFiles) { | 42 | for (const file of video.VideoFiles) { |
43 | currentFile = getVideoFilePath(video, file) | 43 | currentFilePath = getVideoFilePath(video, file) |
44 | 44 | ||
45 | const [ videoBitrate, fps, resolution ] = await Promise.all([ | 45 | const [ videoBitrate, fps, resolution ] = await Promise.all([ |
46 | getVideoFileBitrate(currentFile), | 46 | getVideoFileBitrate(currentFilePath), |
47 | getVideoFileFPS(currentFile), | 47 | getVideoFileFPS(currentFilePath), |
48 | getVideoFileResolution(currentFile) | 48 | getVideoFileResolution(currentFilePath) |
49 | ]) | 49 | ]) |
50 | 50 | ||
51 | const maxBitrate = getMaxBitrate(resolution.videoFileResolution, fps, VIDEO_TRANSCODING_FPS) | 51 | const maxBitrate = getMaxBitrate(resolution.videoFileResolution, fps, VIDEO_TRANSCODING_FPS) |
@@ -53,25 +53,27 @@ async function run () { | |||
53 | if (isMaxBitrateExceeded) { | 53 | if (isMaxBitrateExceeded) { |
54 | console.log( | 54 | console.log( |
55 | 'Optimizing video file %s with bitrate %s kbps (max: %s kbps)', | 55 | 'Optimizing video file %s with bitrate %s kbps (max: %s kbps)', |
56 | basename(currentFile), videoBitrate / 1000, maxBitrate / 1000 | 56 | basename(currentFilePath), videoBitrate / 1000, maxBitrate / 1000 |
57 | ) | 57 | ) |
58 | 58 | ||
59 | const backupFile = `${currentFile}_backup` | 59 | const backupFile = `${currentFilePath}_backup` |
60 | await copy(currentFile, backupFile) | 60 | await copy(currentFilePath, backupFile) |
61 | 61 | ||
62 | await optimizeOriginalVideofile(video, file) | 62 | await optimizeOriginalVideofile(video, file) |
63 | // Update file path, the video filename changed | ||
64 | currentFilePath = getVideoFilePath(video, file) | ||
63 | 65 | ||
64 | const originalDuration = await getDurationFromVideoFile(backupFile) | 66 | const originalDuration = await getDurationFromVideoFile(backupFile) |
65 | const newDuration = await getDurationFromVideoFile(currentFile) | 67 | const newDuration = await getDurationFromVideoFile(currentFilePath) |
66 | 68 | ||
67 | if (originalDuration === newDuration) { | 69 | if (originalDuration === newDuration) { |
68 | console.log('Finished optimizing %s', basename(currentFile)) | 70 | console.log('Finished optimizing %s', basename(currentFilePath)) |
69 | await remove(backupFile) | 71 | await remove(backupFile) |
70 | continue | 72 | continue |
71 | } | 73 | } |
72 | 74 | ||
73 | console.log('Failed to optimize %s, restoring original', basename(currentFile)) | 75 | console.log('Failed to optimize %s, restoring original', basename(currentFilePath)) |
74 | await move(backupFile, currentFile, { overwrite: true }) | 76 | await move(backupFile, currentFilePath, { overwrite: true }) |
75 | await createTorrentAndSetInfoHash(video, file) | 77 | await createTorrentAndSetInfoHash(video, file) |
76 | await file.save() | 78 | await file.save() |
77 | } | 79 | } |
diff --git a/scripts/prune-storage.ts b/scripts/prune-storage.ts index 58d24816e..5b029d215 100755 --- a/scripts/prune-storage.ts +++ b/scripts/prune-storage.ts | |||
@@ -2,11 +2,11 @@ import { registerTSPaths } from '../server/helpers/register-ts-paths' | |||
2 | registerTSPaths() | 2 | registerTSPaths() |
3 | 3 | ||
4 | import * as prompt from 'prompt' | 4 | import * as prompt from 'prompt' |
5 | import { join } from 'path' | 5 | import { join, basename } from 'path' |
6 | import { CONFIG } from '../server/initializers/config' | 6 | import { CONFIG } from '../server/initializers/config' |
7 | import { VideoModel } from '../server/models/video/video' | 7 | import { VideoModel } from '../server/models/video/video' |
8 | import { initDatabaseModels } from '../server/initializers/database' | 8 | import { initDatabaseModels } from '../server/initializers/database' |
9 | import { readdir, remove } from 'fs-extra' | 9 | import { readdir, remove, stat } from 'fs-extra' |
10 | import { VideoRedundancyModel } from '../server/models/redundancy/video-redundancy' | 10 | import { VideoRedundancyModel } from '../server/models/redundancy/video-redundancy' |
11 | import * as Bluebird from 'bluebird' | 11 | import * as Bluebird from 'bluebird' |
12 | import { getUUIDFromFilename } from '../server/helpers/utils' | 12 | import { getUUIDFromFilename } from '../server/helpers/utils' |
@@ -14,6 +14,7 @@ import { ThumbnailModel } from '../server/models/video/thumbnail' | |||
14 | import { ActorImageModel } from '../server/models/actor/actor-image' | 14 | import { ActorImageModel } from '../server/models/actor/actor-image' |
15 | import { uniq, values } from 'lodash' | 15 | import { uniq, values } from 'lodash' |
16 | import { ThumbnailType } from '@shared/models' | 16 | import { ThumbnailType } from '@shared/models' |
17 | import { VideoFileModel } from '@server/models/video/video-file' | ||
17 | 18 | ||
18 | run() | 19 | run() |
19 | .then(() => process.exit(0)) | 20 | .then(() => process.exit(0)) |
@@ -37,8 +38,8 @@ async function run () { | |||
37 | console.log('Detecting files to remove, it could take a while...') | 38 | console.log('Detecting files to remove, it could take a while...') |
38 | 39 | ||
39 | toDelete = toDelete.concat( | 40 | toDelete = toDelete.concat( |
40 | await pruneDirectory(CONFIG.STORAGE.VIDEOS_DIR, doesVideoExist(true)), | 41 | await pruneDirectory(CONFIG.STORAGE.VIDEOS_DIR, doesWebTorrentFileExist()), |
41 | await pruneDirectory(CONFIG.STORAGE.TORRENTS_DIR, doesVideoExist(true)), | 42 | await pruneDirectory(CONFIG.STORAGE.TORRENTS_DIR, doesTorrentFileExist()), |
42 | 43 | ||
43 | await pruneDirectory(CONFIG.STORAGE.REDUNDANCY_DIR, doesRedundancyExist), | 44 | await pruneDirectory(CONFIG.STORAGE.REDUNDANCY_DIR, doesRedundancyExist), |
44 | 45 | ||
@@ -78,26 +79,27 @@ async function pruneDirectory (directory: string, existFun: ExistFun) { | |||
78 | 79 | ||
79 | const toDelete: string[] = [] | 80 | const toDelete: string[] = [] |
80 | await Bluebird.map(files, async file => { | 81 | await Bluebird.map(files, async file => { |
81 | if (await existFun(file) !== true) { | 82 | const filePath = join(directory, file) |
82 | toDelete.push(join(directory, file)) | 83 | |
84 | if (await existFun(filePath) !== true) { | ||
85 | toDelete.push(filePath) | ||
83 | } | 86 | } |
84 | }, { concurrency: 20 }) | 87 | }, { concurrency: 20 }) |
85 | 88 | ||
86 | return toDelete | 89 | return toDelete |
87 | } | 90 | } |
88 | 91 | ||
89 | function doesVideoExist (keepOnlyOwned: boolean) { | 92 | function doesWebTorrentFileExist () { |
90 | return async (file: string) => { | 93 | return (filePath: string) => VideoFileModel.doesOwnedWebTorrentVideoFileExist(basename(filePath)) |
91 | const uuid = getUUIDFromFilename(file) | 94 | } |
92 | const video = await VideoModel.load(uuid) | ||
93 | 95 | ||
94 | return video && (keepOnlyOwned === false || video.isOwned()) | 96 | function doesTorrentFileExist () { |
95 | } | 97 | return (filePath: string) => VideoFileModel.doesOwnedTorrentFileExist(basename(filePath)) |
96 | } | 98 | } |
97 | 99 | ||
98 | function doesThumbnailExist (keepOnlyOwned: boolean, type: ThumbnailType) { | 100 | function doesThumbnailExist (keepOnlyOwned: boolean, type: ThumbnailType) { |
99 | return async (file: string) => { | 101 | return async (filePath: string) => { |
100 | const thumbnail = await ThumbnailModel.loadByFilename(file, type) | 102 | const thumbnail = await ThumbnailModel.loadByFilename(basename(filePath), type) |
101 | if (!thumbnail) return false | 103 | if (!thumbnail) return false |
102 | 104 | ||
103 | if (keepOnlyOwned) { | 105 | if (keepOnlyOwned) { |
@@ -109,21 +111,20 @@ function doesThumbnailExist (keepOnlyOwned: boolean, type: ThumbnailType) { | |||
109 | } | 111 | } |
110 | } | 112 | } |
111 | 113 | ||
112 | async function doesActorImageExist (file: string) { | 114 | async function doesActorImageExist (filePath: string) { |
113 | const image = await ActorImageModel.loadByName(file) | 115 | const image = await ActorImageModel.loadByName(basename(filePath)) |
114 | 116 | ||
115 | return !!image | 117 | return !!image |
116 | } | 118 | } |
117 | 119 | ||
118 | async function doesRedundancyExist (file: string) { | 120 | async function doesRedundancyExist (filePath: string) { |
119 | const uuid = getUUIDFromFilename(file) | 121 | const isPlaylist = (await stat(filePath)).isDirectory() |
120 | const video = await VideoModel.loadWithFiles(uuid) | ||
121 | |||
122 | if (!video) return false | ||
123 | |||
124 | const isPlaylist = file.includes('.') === false | ||
125 | 122 | ||
126 | if (isPlaylist) { | 123 | if (isPlaylist) { |
124 | const uuid = getUUIDFromFilename(filePath) | ||
125 | const video = await VideoModel.loadWithFiles(uuid) | ||
126 | if (!video) return false | ||
127 | |||
127 | const p = video.getHLSPlaylist() | 128 | const p = video.getHLSPlaylist() |
128 | if (!p) return false | 129 | if (!p) return false |
129 | 130 | ||
@@ -131,19 +132,10 @@ async function doesRedundancyExist (file: string) { | |||
131 | return !!redundancy | 132 | return !!redundancy |
132 | } | 133 | } |
133 | 134 | ||
134 | const resolution = parseInt(file.split('-')[5], 10) | 135 | const file = await VideoFileModel.loadByFilename(basename(filePath)) |
135 | if (isNaN(resolution)) { | 136 | if (!file) return false |
136 | console.error('Cannot prune %s because we cannot guess guess the resolution.', file) | ||
137 | return true | ||
138 | } | ||
139 | |||
140 | const videoFile = video.getWebTorrentFile(resolution) | ||
141 | if (!videoFile) { | ||
142 | console.error('Cannot find webtorrent file of video %s - %d', video.url, resolution) | ||
143 | return true | ||
144 | } | ||
145 | 137 | ||
146 | const redundancy = await VideoRedundancyModel.loadLocalByFileId(videoFile.id) | 138 | const redundancy = await VideoRedundancyModel.loadLocalByFileId(file.id) |
147 | return !!redundancy | 139 | return !!redundancy |
148 | } | 140 | } |
149 | 141 | ||
diff --git a/scripts/update-host.ts b/scripts/update-host.ts index 592684225..9e8dd41ca 100755 --- a/scripts/update-host.ts +++ b/scripts/update-host.ts | |||
@@ -16,7 +16,6 @@ import { VideoShareModel } from '../server/models/video/video-share' | |||
16 | import { VideoCommentModel } from '../server/models/video/video-comment' | 16 | import { VideoCommentModel } from '../server/models/video/video-comment' |
17 | import { AccountModel } from '../server/models/account/account' | 17 | import { AccountModel } from '../server/models/account/account' |
18 | import { VideoChannelModel } from '../server/models/video/video-channel' | 18 | import { VideoChannelModel } from '../server/models/video/video-channel' |
19 | import { VideoStreamingPlaylistModel } from '../server/models/video/video-streaming-playlist' | ||
20 | import { initDatabaseModels } from '../server/initializers/database' | 19 | import { initDatabaseModels } from '../server/initializers/database' |
21 | import { createTorrentAndSetInfoHash } from '@server/helpers/webtorrent' | 20 | import { createTorrentAndSetInfoHash } from '@server/helpers/webtorrent' |
22 | import { getServerActor } from '@server/models/application/application' | 21 | import { getServerActor } from '@server/models/application/application' |
@@ -128,13 +127,17 @@ async function run () { | |||
128 | for (const file of video.VideoFiles) { | 127 | for (const file of video.VideoFiles) { |
129 | console.log('Updating torrent file %s of video %s.', file.resolution, video.uuid) | 128 | console.log('Updating torrent file %s of video %s.', file.resolution, video.uuid) |
130 | await createTorrentAndSetInfoHash(video, file) | 129 | await createTorrentAndSetInfoHash(video, file) |
130 | |||
131 | await file.save() | ||
131 | } | 132 | } |
132 | 133 | ||
133 | for (const playlist of video.VideoStreamingPlaylists) { | 134 | const playlist = video.getHLSPlaylist() |
134 | playlist.playlistUrl = WEBSERVER.URL + VideoStreamingPlaylistModel.getHlsMasterPlaylistStaticPath(video.uuid) | 135 | for (const file of (playlist?.VideoFiles || [])) { |
135 | playlist.segmentsSha256Url = WEBSERVER.URL + VideoStreamingPlaylistModel.getHlsSha256SegmentsStaticPath(video.uuid, video.isLive) | 136 | console.log('Updating fragmented torrent file %s of video %s.', file.resolution, video.uuid) |
137 | |||
138 | await createTorrentAndSetInfoHash(video, file) | ||
136 | 139 | ||
137 | await playlist.save() | 140 | await file.save() |
138 | } | 141 | } |
139 | } | 142 | } |
140 | } | 143 | } |