diff options
author | Chocobozzz <me@florianbigard.com> | 2022-02-11 10:51:33 +0100 |
---|---|---|
committer | Chocobozzz <chocobozzz@cpy.re> | 2022-02-28 10:42:19 +0100 |
commit | c729caf6cc34630877a0e5a1bda1719384cd0c8a (patch) | |
tree | 1d2e13722e518c73d2c9e6f0969615e29d51cf8c /server/lib/transcoding | |
parent | a24bf4dc659cebb65d887862bf21d7a35e9ec791 (diff) | |
download | PeerTube-c729caf6cc34630877a0e5a1bda1719384cd0c8a.tar.gz PeerTube-c729caf6cc34630877a0e5a1bda1719384cd0c8a.tar.zst PeerTube-c729caf6cc34630877a0e5a1bda1719384cd0c8a.zip |
Add basic video editor support
Diffstat (limited to 'server/lib/transcoding')
-rw-r--r-- | server/lib/transcoding/default-transcoding-profiles.ts (renamed from server/lib/transcoding/video-transcoding-profiles.ts) | 25 | ||||
-rw-r--r-- | server/lib/transcoding/transcoding.ts (renamed from server/lib/transcoding/video-transcoding.ts) | 35 |
2 files changed, 41 insertions, 19 deletions
diff --git a/server/lib/transcoding/video-transcoding-profiles.ts b/server/lib/transcoding/default-transcoding-profiles.ts index dcc8d4c5c..ba98a11ca 100644 --- a/server/lib/transcoding/video-transcoding-profiles.ts +++ b/server/lib/transcoding/default-transcoding-profiles.ts | |||
@@ -2,8 +2,14 @@ | |||
2 | import { logger } from '@server/helpers/logger' | 2 | import { logger } from '@server/helpers/logger' |
3 | import { getAverageBitrate, getMinLimitBitrate } from '@shared/core-utils' | 3 | import { getAverageBitrate, getMinLimitBitrate } from '@shared/core-utils' |
4 | import { AvailableEncoders, EncoderOptionsBuilder, EncoderOptionsBuilderParams, VideoResolution } from '../../../shared/models/videos' | 4 | import { AvailableEncoders, EncoderOptionsBuilder, EncoderOptionsBuilderParams, VideoResolution } from '../../../shared/models/videos' |
5 | import { buildStreamSuffix, resetSupportedEncoders } from '../../helpers/ffmpeg-utils' | 5 | import { |
6 | import { canDoQuickAudioTranscode, ffprobePromise, getAudioStream, getMaxAudioBitrate } from '../../helpers/ffprobe-utils' | 6 | buildStreamSuffix, |
7 | canDoQuickAudioTranscode, | ||
8 | ffprobePromise, | ||
9 | getAudioStream, | ||
10 | getMaxAudioBitrate, | ||
11 | resetSupportedEncoders | ||
12 | } from '../../helpers/ffmpeg' | ||
7 | 13 | ||
8 | /** | 14 | /** |
9 | * | 15 | * |
@@ -15,8 +21,14 @@ import { canDoQuickAudioTranscode, ffprobePromise, getAudioStream, getMaxAudioBi | |||
15 | * * https://trac.ffmpeg.org/wiki/Limiting%20the%20output%20bitrate | 21 | * * https://trac.ffmpeg.org/wiki/Limiting%20the%20output%20bitrate |
16 | */ | 22 | */ |
17 | 23 | ||
24 | // --------------------------------------------------------------------------- | ||
25 | // Default builders | ||
26 | // --------------------------------------------------------------------------- | ||
27 | |||
18 | const defaultX264VODOptionsBuilder: EncoderOptionsBuilder = (options: EncoderOptionsBuilderParams) => { | 28 | const defaultX264VODOptionsBuilder: EncoderOptionsBuilder = (options: EncoderOptionsBuilderParams) => { |
19 | const { fps, inputRatio, inputBitrate, resolution } = options | 29 | const { fps, inputRatio, inputBitrate, resolution } = options |
30 | |||
31 | // TODO: remove in 4.2, fps is not optional anymore | ||
20 | if (!fps) return { outputOptions: [ ] } | 32 | if (!fps) return { outputOptions: [ ] } |
21 | 33 | ||
22 | const targetBitrate = getTargetBitrate({ inputBitrate, ratio: inputRatio, fps, resolution }) | 34 | const targetBitrate = getTargetBitrate({ inputBitrate, ratio: inputRatio, fps, resolution }) |
@@ -45,10 +57,10 @@ const defaultX264LiveOptionsBuilder: EncoderOptionsBuilder = (options: EncoderOp | |||
45 | } | 57 | } |
46 | } | 58 | } |
47 | 59 | ||
48 | const defaultAACOptionsBuilder: EncoderOptionsBuilder = async ({ input, streamNum }) => { | 60 | const defaultAACOptionsBuilder: EncoderOptionsBuilder = async ({ input, streamNum, canCopyAudio }) => { |
49 | const probe = await ffprobePromise(input) | 61 | const probe = await ffprobePromise(input) |
50 | 62 | ||
51 | if (await canDoQuickAudioTranscode(input, probe)) { | 63 | if (canCopyAudio && await canDoQuickAudioTranscode(input, probe)) { |
52 | logger.debug('Copy audio stream %s by AAC encoder.', input) | 64 | logger.debug('Copy audio stream %s by AAC encoder.', input) |
53 | return { copy: true, outputOptions: [ ] } | 65 | return { copy: true, outputOptions: [ ] } |
54 | } | 66 | } |
@@ -75,7 +87,10 @@ const defaultLibFDKAACVODOptionsBuilder: EncoderOptionsBuilder = ({ streamNum }) | |||
75 | return { outputOptions: [ buildStreamSuffix('-q:a', streamNum), '5' ] } | 87 | return { outputOptions: [ buildStreamSuffix('-q:a', streamNum), '5' ] } |
76 | } | 88 | } |
77 | 89 | ||
78 | // Used to get and update available encoders | 90 | // --------------------------------------------------------------------------- |
91 | // Profile manager to get and change default profiles | ||
92 | // --------------------------------------------------------------------------- | ||
93 | |||
79 | class VideoTranscodingProfilesManager { | 94 | class VideoTranscodingProfilesManager { |
80 | private static instance: VideoTranscodingProfilesManager | 95 | private static instance: VideoTranscodingProfilesManager |
81 | 96 | ||
diff --git a/server/lib/transcoding/video-transcoding.ts b/server/lib/transcoding/transcoding.ts index 9942a067b..d55364e25 100644 --- a/server/lib/transcoding/video-transcoding.ts +++ b/server/lib/transcoding/transcoding.ts | |||
@@ -6,8 +6,15 @@ import { createTorrentAndSetInfoHash } from '@server/helpers/webtorrent' | |||
6 | import { MStreamingPlaylistFilesVideo, MVideoFile, MVideoFullLight } from '@server/types/models' | 6 | import { MStreamingPlaylistFilesVideo, MVideoFile, MVideoFullLight } from '@server/types/models' |
7 | import { VideoResolution, VideoStorage } from '../../../shared/models/videos' | 7 | import { VideoResolution, VideoStorage } from '../../../shared/models/videos' |
8 | import { VideoStreamingPlaylistType } from '../../../shared/models/videos/video-streaming-playlist.type' | 8 | import { VideoStreamingPlaylistType } from '../../../shared/models/videos/video-streaming-playlist.type' |
9 | import { transcode, TranscodeOptions, TranscodeOptionsType } from '../../helpers/ffmpeg-utils' | 9 | import { |
10 | import { canDoQuickTranscode, getDurationFromVideoFile, getMetadataFromFile, getVideoFileFPS } from '../../helpers/ffprobe-utils' | 10 | canDoQuickTranscode, |
11 | getVideoStreamDuration, | ||
12 | buildFileMetadata, | ||
13 | getVideoStreamFPS, | ||
14 | transcodeVOD, | ||
15 | TranscodeVODOptions, | ||
16 | TranscodeVODOptionsType | ||
17 | } from '../../helpers/ffmpeg' | ||
11 | import { CONFIG } from '../../initializers/config' | 18 | import { CONFIG } from '../../initializers/config' |
12 | import { P2P_MEDIA_LOADER_PEER_VERSION } from '../../initializers/constants' | 19 | import { P2P_MEDIA_LOADER_PEER_VERSION } from '../../initializers/constants' |
13 | import { VideoFileModel } from '../../models/video/video-file' | 20 | import { VideoFileModel } from '../../models/video/video-file' |
@@ -21,7 +28,7 @@ import { | |||
21 | getHlsResolutionPlaylistFilename | 28 | getHlsResolutionPlaylistFilename |
22 | } from '../paths' | 29 | } from '../paths' |
23 | import { VideoPathManager } from '../video-path-manager' | 30 | import { VideoPathManager } from '../video-path-manager' |
24 | import { VideoTranscodingProfilesManager } from './video-transcoding-profiles' | 31 | import { VideoTranscodingProfilesManager } from './default-transcoding-profiles' |
25 | 32 | ||
26 | /** | 33 | /** |
27 | * | 34 | * |
@@ -38,13 +45,13 @@ function optimizeOriginalVideofile (video: MVideoFullLight, inputVideoFile: MVid | |||
38 | return VideoPathManager.Instance.makeAvailableVideoFile(inputVideoFile.withVideoOrPlaylist(video), async videoInputPath => { | 45 | return VideoPathManager.Instance.makeAvailableVideoFile(inputVideoFile.withVideoOrPlaylist(video), async videoInputPath => { |
39 | const videoTranscodedPath = join(transcodeDirectory, video.id + '-transcoded' + newExtname) | 46 | const videoTranscodedPath = join(transcodeDirectory, video.id + '-transcoded' + newExtname) |
40 | 47 | ||
41 | const transcodeType: TranscodeOptionsType = await canDoQuickTranscode(videoInputPath) | 48 | const transcodeType: TranscodeVODOptionsType = await canDoQuickTranscode(videoInputPath) |
42 | ? 'quick-transcode' | 49 | ? 'quick-transcode' |
43 | : 'video' | 50 | : 'video' |
44 | 51 | ||
45 | const resolution = toEven(inputVideoFile.resolution) | 52 | const resolution = toEven(inputVideoFile.resolution) |
46 | 53 | ||
47 | const transcodeOptions: TranscodeOptions = { | 54 | const transcodeOptions: TranscodeVODOptions = { |
48 | type: transcodeType, | 55 | type: transcodeType, |
49 | 56 | ||
50 | inputPath: videoInputPath, | 57 | inputPath: videoInputPath, |
@@ -59,7 +66,7 @@ function optimizeOriginalVideofile (video: MVideoFullLight, inputVideoFile: MVid | |||
59 | } | 66 | } |
60 | 67 | ||
61 | // Could be very long! | 68 | // Could be very long! |
62 | await transcode(transcodeOptions) | 69 | await transcodeVOD(transcodeOptions) |
63 | 70 | ||
64 | // Important to do this before getVideoFilename() to take in account the new filename | 71 | // Important to do this before getVideoFilename() to take in account the new filename |
65 | inputVideoFile.extname = newExtname | 72 | inputVideoFile.extname = newExtname |
@@ -121,7 +128,7 @@ function transcodeNewWebTorrentResolution (video: MVideoFullLight, resolution: V | |||
121 | job | 128 | job |
122 | } | 129 | } |
123 | 130 | ||
124 | await transcode(transcodeOptions) | 131 | await transcodeVOD(transcodeOptions) |
125 | 132 | ||
126 | return onWebTorrentVideoFileTranscoding(video, newVideoFile, videoTranscodedPath, videoOutputPath) | 133 | return onWebTorrentVideoFileTranscoding(video, newVideoFile, videoTranscodedPath, videoOutputPath) |
127 | }) | 134 | }) |
@@ -158,7 +165,7 @@ function mergeAudioVideofile (video: MVideoFullLight, resolution: VideoResolutio | |||
158 | } | 165 | } |
159 | 166 | ||
160 | try { | 167 | try { |
161 | await transcode(transcodeOptions) | 168 | await transcodeVOD(transcodeOptions) |
162 | 169 | ||
163 | await remove(audioInputPath) | 170 | await remove(audioInputPath) |
164 | await remove(tmpPreviewPath) | 171 | await remove(tmpPreviewPath) |
@@ -175,7 +182,7 @@ function mergeAudioVideofile (video: MVideoFullLight, resolution: VideoResolutio | |||
175 | const videoOutputPath = VideoPathManager.Instance.getFSVideoFileOutputPath(video, inputVideoFile) | 182 | const videoOutputPath = VideoPathManager.Instance.getFSVideoFileOutputPath(video, inputVideoFile) |
176 | // ffmpeg generated a new video file, so update the video duration | 183 | // ffmpeg generated a new video file, so update the video duration |
177 | // See https://trac.ffmpeg.org/ticket/5456 | 184 | // See https://trac.ffmpeg.org/ticket/5456 |
178 | video.duration = await getDurationFromVideoFile(videoTranscodedPath) | 185 | video.duration = await getVideoStreamDuration(videoTranscodedPath) |
179 | await video.save() | 186 | await video.save() |
180 | 187 | ||
181 | return onWebTorrentVideoFileTranscoding(video, inputVideoFile, videoTranscodedPath, videoOutputPath) | 188 | return onWebTorrentVideoFileTranscoding(video, inputVideoFile, videoTranscodedPath, videoOutputPath) |
@@ -239,8 +246,8 @@ async function onWebTorrentVideoFileTranscoding ( | |||
239 | outputPath: string | 246 | outputPath: string |
240 | ) { | 247 | ) { |
241 | const stats = await stat(transcodingPath) | 248 | const stats = await stat(transcodingPath) |
242 | const fps = await getVideoFileFPS(transcodingPath) | 249 | const fps = await getVideoStreamFPS(transcodingPath) |
243 | const metadata = await getMetadataFromFile(transcodingPath) | 250 | const metadata = await buildFileMetadata(transcodingPath) |
244 | 251 | ||
245 | await move(transcodingPath, outputPath, { overwrite: true }) | 252 | await move(transcodingPath, outputPath, { overwrite: true }) |
246 | 253 | ||
@@ -299,7 +306,7 @@ async function generateHlsPlaylistCommon (options: { | |||
299 | job | 306 | job |
300 | } | 307 | } |
301 | 308 | ||
302 | await transcode(transcodeOptions) | 309 | await transcodeVOD(transcodeOptions) |
303 | 310 | ||
304 | // Create or update the playlist | 311 | // Create or update the playlist |
305 | const playlist = await VideoStreamingPlaylistModel.loadOrGenerate(video) | 312 | const playlist = await VideoStreamingPlaylistModel.loadOrGenerate(video) |
@@ -344,8 +351,8 @@ async function generateHlsPlaylistCommon (options: { | |||
344 | const stats = await stat(videoFilePath) | 351 | const stats = await stat(videoFilePath) |
345 | 352 | ||
346 | newVideoFile.size = stats.size | 353 | newVideoFile.size = stats.size |
347 | newVideoFile.fps = await getVideoFileFPS(videoFilePath) | 354 | newVideoFile.fps = await getVideoStreamFPS(videoFilePath) |
348 | newVideoFile.metadata = await getMetadataFromFile(videoFilePath) | 355 | newVideoFile.metadata = await buildFileMetadata(videoFilePath) |
349 | 356 | ||
350 | await createTorrentAndSetInfoHash(playlist, newVideoFile) | 357 | await createTorrentAndSetInfoHash(playlist, newVideoFile) |
351 | 358 | ||