]>
Commit | Line | Data |
---|---|---|
1 | import { CONFIG } from '../initializers' | |
2 | import { extname, join } from 'path' | |
3 | import { getVideoFileFPS, getVideoFileResolution, transcode } from '../helpers/ffmpeg-utils' | |
4 | import { copy, remove, move, 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 optimizeVideofile (video: VideoModel, inputVideoFileArg?: VideoFileModel) { | |
11 | const videosDirectory = CONFIG.STORAGE.VIDEOS_DIR | |
12 | const newExtname = '.mp4' | |
13 | ||
14 | const inputVideoFile = inputVideoFileArg ? inputVideoFileArg : video.getOriginalFile() | |
15 | const videoInputPath = join(videosDirectory, video.getVideoFilename(inputVideoFile)) | |
16 | const videoTranscodedPath = join(videosDirectory, video.id + '-transcoded' + newExtname) | |
17 | ||
18 | const transcodeOptions = { | |
19 | inputPath: videoInputPath, | |
20 | outputPath: videoTranscodedPath | |
21 | } | |
22 | ||
23 | // Could be very long! | |
24 | await transcode(transcodeOptions) | |
25 | ||
26 | try { | |
27 | await remove(videoInputPath) | |
28 | ||
29 | // Important to do this before getVideoFilename() to take in account the new file extension | |
30 | inputVideoFile.set('extname', newExtname) | |
31 | ||
32 | const videoOutputPath = video.getVideoFilePath(inputVideoFile) | |
33 | await move(videoTranscodedPath, videoOutputPath) | |
34 | const stats = await stat(videoOutputPath) | |
35 | const fps = await getVideoFileFPS(videoOutputPath) | |
36 | ||
37 | inputVideoFile.set('size', stats.size) | |
38 | inputVideoFile.set('fps', fps) | |
39 | ||
40 | await video.createTorrentAndSetInfoHash(inputVideoFile) | |
41 | await inputVideoFile.save() | |
42 | } catch (err) { | |
43 | // Auto destruction... | |
44 | video.destroy().catch(err => logger.error('Cannot destruct video after transcoding failure.', { err })) | |
45 | ||
46 | throw err | |
47 | } | |
48 | } | |
49 | ||
50 | async function transcodeOriginalVideofile (video: VideoModel, resolution: VideoResolution, isPortraitMode: boolean) { | |
51 | const videosDirectory = CONFIG.STORAGE.VIDEOS_DIR | |
52 | const extname = '.mp4' | |
53 | ||
54 | // We are sure it's x264 in mp4 because optimizeOriginalVideofile was already executed | |
55 | const videoInputPath = join(videosDirectory, video.getVideoFilename(video.getOriginalFile())) | |
56 | ||
57 | const newVideoFile = new VideoFileModel({ | |
58 | resolution, | |
59 | extname, | |
60 | size: 0, | |
61 | videoId: video.id | |
62 | }) | |
63 | const videoOutputPath = join(videosDirectory, video.getVideoFilename(newVideoFile)) | |
64 | ||
65 | const transcodeOptions = { | |
66 | inputPath: videoInputPath, | |
67 | outputPath: videoOutputPath, | |
68 | resolution, | |
69 | isPortraitMode | |
70 | } | |
71 | ||
72 | await transcode(transcodeOptions) | |
73 | ||
74 | const stats = await stat(videoOutputPath) | |
75 | const fps = await getVideoFileFPS(videoOutputPath) | |
76 | ||
77 | newVideoFile.set('size', stats.size) | |
78 | newVideoFile.set('fps', fps) | |
79 | ||
80 | await video.createTorrentAndSetInfoHash(newVideoFile) | |
81 | ||
82 | await newVideoFile.save() | |
83 | ||
84 | video.VideoFiles.push(newVideoFile) | |
85 | } | |
86 | ||
87 | async function importVideoFile (video: VideoModel, inputFilePath: string) { | |
88 | const { videoFileResolution } = await getVideoFileResolution(inputFilePath) | |
89 | const { size } = await stat(inputFilePath) | |
90 | const fps = await getVideoFileFPS(inputFilePath) | |
91 | ||
92 | let updatedVideoFile = new VideoFileModel({ | |
93 | resolution: videoFileResolution, | |
94 | extname: extname(inputFilePath), | |
95 | size, | |
96 | fps, | |
97 | videoId: video.id | |
98 | }) | |
99 | ||
100 | const currentVideoFile = video.VideoFiles.find(videoFile => videoFile.resolution === updatedVideoFile.resolution) | |
101 | ||
102 | if (currentVideoFile) { | |
103 | // Remove old file and old torrent | |
104 | await video.removeFile(currentVideoFile) | |
105 | await video.removeTorrent(currentVideoFile) | |
106 | // Remove the old video file from the array | |
107 | video.VideoFiles = video.VideoFiles.filter(f => f !== currentVideoFile) | |
108 | ||
109 | // Update the database | |
110 | currentVideoFile.set('extname', updatedVideoFile.extname) | |
111 | currentVideoFile.set('size', updatedVideoFile.size) | |
112 | currentVideoFile.set('fps', updatedVideoFile.fps) | |
113 | ||
114 | updatedVideoFile = currentVideoFile | |
115 | } | |
116 | ||
117 | const outputPath = video.getVideoFilePath(updatedVideoFile) | |
118 | await copy(inputFilePath, outputPath) | |
119 | ||
120 | await video.createTorrentAndSetInfoHash(updatedVideoFile) | |
121 | ||
122 | await updatedVideoFile.save() | |
123 | ||
124 | video.VideoFiles.push(updatedVideoFile) | |
125 | } | |
126 | ||
127 | export { | |
128 | optimizeVideofile, | |
129 | transcodeOriginalVideofile, | |
130 | importVideoFile | |
131 | } |