diff options
author | Chocobozzz <me@florianbigard.com> | 2018-09-20 16:24:31 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-09-20 16:24:31 +0200 |
commit | 0491173a61aed66205c017e0d7e0503ea316c144 (patch) | |
tree | ce6621597505f9518cfdf0981977d097c63f9fad /server/lib/video-transcoding.ts | |
parent | 8704acf49efc770d73bf07c10468ed8c74d28a83 (diff) | |
parent | 6247b2057b792cea155a1abd9788c363ae7d2cc2 (diff) | |
download | PeerTube-0491173a61aed66205c017e0d7e0503ea316c144.tar.gz PeerTube-0491173a61aed66205c017e0d7e0503ea316c144.tar.zst PeerTube-0491173a61aed66205c017e0d7e0503ea316c144.zip |
Merge branch 'develop' into cli-wrapper
Diffstat (limited to 'server/lib/video-transcoding.ts')
-rw-r--r-- | server/lib/video-transcoding.ts | 130 |
1 files changed, 130 insertions, 0 deletions
diff --git a/server/lib/video-transcoding.ts b/server/lib/video-transcoding.ts new file mode 100644 index 000000000..bf3ff78c2 --- /dev/null +++ b/server/lib/video-transcoding.ts | |||
@@ -0,0 +1,130 @@ | |||
1 | import { CONFIG } from '../initializers' | ||
2 | import { join, extname } from 'path' | ||
3 | import { getVideoFileFPS, getVideoFileResolution, transcode } from '../helpers/ffmpeg-utils' | ||
4 | import { copy, remove, rename, stat } from 'fs-extra' | ||
5 | import { logger } from '../helpers/logger' | ||
6 | import { VideoResolution } from '../../shared/models/videos' | ||
7 | import { VideoFileModel } from '../models/video/video-file' | ||
8 | import { VideoModel } from '../models/video/video' | ||
9 | |||
10 | async function optimizeOriginalVideofile (video: VideoModel) { | ||
11 | const videosDirectory = CONFIG.STORAGE.VIDEOS_DIR | ||
12 | const newExtname = '.mp4' | ||
13 | const inputVideoFile = video.getOriginalFile() | ||
14 | const videoInputPath = join(videosDirectory, video.getVideoFilename(inputVideoFile)) | ||
15 | const videoTranscodedPath = join(videosDirectory, video.id + '-transcoded' + newExtname) | ||
16 | |||
17 | const transcodeOptions = { | ||
18 | inputPath: videoInputPath, | ||
19 | outputPath: videoTranscodedPath | ||
20 | } | ||
21 | |||
22 | // Could be very long! | ||
23 | await transcode(transcodeOptions) | ||
24 | |||
25 | try { | ||
26 | await remove(videoInputPath) | ||
27 | |||
28 | // Important to do this before getVideoFilename() to take in account the new file extension | ||
29 | inputVideoFile.set('extname', newExtname) | ||
30 | |||
31 | const videoOutputPath = video.getVideoFilePath(inputVideoFile) | ||
32 | await rename(videoTranscodedPath, videoOutputPath) | ||
33 | const stats = await stat(videoOutputPath) | ||
34 | const fps = await getVideoFileFPS(videoOutputPath) | ||
35 | |||
36 | inputVideoFile.set('size', stats.size) | ||
37 | inputVideoFile.set('fps', fps) | ||
38 | |||
39 | await video.createTorrentAndSetInfoHash(inputVideoFile) | ||
40 | await inputVideoFile.save() | ||
41 | } catch (err) { | ||
42 | // Auto destruction... | ||
43 | video.destroy().catch(err => logger.error('Cannot destruct video after transcoding failure.', { err })) | ||
44 | |||
45 | throw err | ||
46 | } | ||
47 | } | ||
48 | |||
49 | async function transcodeOriginalVideofile (video: VideoModel, resolution: VideoResolution, isPortraitMode: boolean) { | ||
50 | const videosDirectory = CONFIG.STORAGE.VIDEOS_DIR | ||
51 | const extname = '.mp4' | ||
52 | |||
53 | // We are sure it's x264 in mp4 because optimizeOriginalVideofile was already executed | ||
54 | const videoInputPath = join(videosDirectory, video.getVideoFilename(video.getOriginalFile())) | ||
55 | |||
56 | const newVideoFile = new VideoFileModel({ | ||
57 | resolution, | ||
58 | extname, | ||
59 | size: 0, | ||
60 | videoId: video.id | ||
61 | }) | ||
62 | const videoOutputPath = join(videosDirectory, video.getVideoFilename(newVideoFile)) | ||
63 | |||
64 | const transcodeOptions = { | ||
65 | inputPath: videoInputPath, | ||
66 | outputPath: videoOutputPath, | ||
67 | resolution, | ||
68 | isPortraitMode | ||
69 | } | ||
70 | |||
71 | await transcode(transcodeOptions) | ||
72 | |||
73 | const stats = await stat(videoOutputPath) | ||
74 | const fps = await getVideoFileFPS(videoOutputPath) | ||
75 | |||
76 | newVideoFile.set('size', stats.size) | ||
77 | newVideoFile.set('fps', fps) | ||
78 | |||
79 | await video.createTorrentAndSetInfoHash(newVideoFile) | ||
80 | |||
81 | await newVideoFile.save() | ||
82 | |||
83 | video.VideoFiles.push(newVideoFile) | ||
84 | } | ||
85 | |||
86 | async function importVideoFile (video: VideoModel, inputFilePath: string) { | ||
87 | const { videoFileResolution } = await getVideoFileResolution(inputFilePath) | ||
88 | const { size } = await stat(inputFilePath) | ||
89 | const fps = await getVideoFileFPS(inputFilePath) | ||
90 | |||
91 | let updatedVideoFile = new VideoFileModel({ | ||
92 | resolution: videoFileResolution, | ||
93 | extname: extname(inputFilePath), | ||
94 | size, | ||
95 | fps, | ||
96 | videoId: video.id | ||
97 | }) | ||
98 | |||
99 | const currentVideoFile = video.VideoFiles.find(videoFile => videoFile.resolution === updatedVideoFile.resolution) | ||
100 | |||
101 | if (currentVideoFile) { | ||
102 | // Remove old file and old torrent | ||
103 | await video.removeFile(currentVideoFile) | ||
104 | await video.removeTorrent(currentVideoFile) | ||
105 | // Remove the old video file from the array | ||
106 | video.VideoFiles = video.VideoFiles.filter(f => f !== currentVideoFile) | ||
107 | |||
108 | // Update the database | ||
109 | currentVideoFile.set('extname', updatedVideoFile.extname) | ||
110 | currentVideoFile.set('size', updatedVideoFile.size) | ||
111 | currentVideoFile.set('fps', updatedVideoFile.fps) | ||
112 | |||
113 | updatedVideoFile = currentVideoFile | ||
114 | } | ||
115 | |||
116 | const outputPath = video.getVideoFilePath(updatedVideoFile) | ||
117 | await copy(inputFilePath, outputPath) | ||
118 | |||
119 | await video.createTorrentAndSetInfoHash(updatedVideoFile) | ||
120 | |||
121 | await updatedVideoFile.save() | ||
122 | |||
123 | video.VideoFiles.push(updatedVideoFile) | ||
124 | } | ||
125 | |||
126 | export { | ||
127 | optimizeOriginalVideofile, | ||
128 | transcodeOriginalVideofile, | ||
129 | importVideoFile | ||
130 | } | ||