aboutsummaryrefslogtreecommitdiffhomepage
path: root/server/lib/video-transcoding.ts
diff options
context:
space:
mode:
Diffstat (limited to 'server/lib/video-transcoding.ts')
-rw-r--r--server/lib/video-transcoding.ts130
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 @@
1import { CONFIG } from '../initializers'
2import { join, extname } from 'path'
3import { getVideoFileFPS, getVideoFileResolution, transcode } from '../helpers/ffmpeg-utils'
4import { copy, remove, rename, stat } from 'fs-extra'
5import { logger } from '../helpers/logger'
6import { VideoResolution } from '../../shared/models/videos'
7import { VideoFileModel } from '../models/video/video-file'
8import { VideoModel } from '../models/video/video'
9
10async 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
49async 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
86async 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
126export {
127 optimizeOriginalVideofile,
128 transcodeOriginalVideofile,
129 importVideoFile
130}