X-Git-Url: https://git.immae.eu/?a=blobdiff_plain;ds=sidebyside;f=server%2Flib%2Fvideo-transcoding.ts;h=8d786e0ef5ea5ba16e7f79e96557072dbc4af98b;hb=536598cfafab1c5e24e881db1c528489f804fb6b;hp=0fe0ff12a4c0aa2fb4f15caba7a547bcaaf33471;hpb=97567dd81f508dd6295ac4d73d849aa2ce0a6549;p=github%2FChocobozzz%2FPeerTube.git diff --git a/server/lib/video-transcoding.ts b/server/lib/video-transcoding.ts index 0fe0ff12a..8d786e0ef 100644 --- a/server/lib/video-transcoding.ts +++ b/server/lib/video-transcoding.ts @@ -1,6 +1,6 @@ import { HLS_STREAMING_PLAYLIST_DIRECTORY, P2P_MEDIA_LOADER_PEER_VERSION, WEBSERVER } from '../initializers/constants' import { join } from 'path' -import { getVideoFileFPS, transcode } from '../helpers/ffmpeg-utils' +import { canDoQuickTranscode, getVideoFileFPS, transcode, TranscodeOptions, TranscodeOptionsType } from '../helpers/ffmpeg-utils' import { ensureDir, move, remove, stat } from 'fs-extra' import { logger } from '../helpers/logger' import { VideoResolution } from '../../shared/models/videos' @@ -11,15 +11,24 @@ import { VideoStreamingPlaylistModel } from '../models/video/video-streaming-pla import { VideoStreamingPlaylistType } from '../../shared/models/videos/video-streaming-playlist.type' import { CONFIG } from '../initializers/config' +/** + * Optimize the original video file and replace it. The resolution is not changed. + */ async function optimizeVideofile (video: VideoModel, inputVideoFileArg?: VideoFileModel) { const videosDirectory = CONFIG.STORAGE.VIDEOS_DIR + const transcodeDirectory = CONFIG.STORAGE.TMP_DIR const newExtname = '.mp4' const inputVideoFile = inputVideoFileArg ? inputVideoFileArg : video.getOriginalFile() const videoInputPath = join(videosDirectory, video.getVideoFilename(inputVideoFile)) - const videoTranscodedPath = join(videosDirectory, video.id + '-transcoded' + newExtname) + const videoTranscodedPath = join(transcodeDirectory, video.id + '-transcoded' + newExtname) - const transcodeOptions = { + const transcodeType: TranscodeOptionsType = await canDoQuickTranscode(videoInputPath) + ? 'quick-transcode' + : 'video' + + const transcodeOptions: TranscodeOptions = { + type: transcodeType as any, // FIXME: typing issue inputPath: videoInputPath, outputPath: videoTranscodedPath, resolution: inputVideoFile.resolution @@ -32,18 +41,11 @@ async function optimizeVideofile (video: VideoModel, inputVideoFileArg?: VideoFi await remove(videoInputPath) // Important to do this before getVideoFilename() to take in account the new file extension - inputVideoFile.set('extname', newExtname) + inputVideoFile.extname = newExtname const videoOutputPath = video.getVideoFilePath(inputVideoFile) - await move(videoTranscodedPath, videoOutputPath) - const stats = await stat(videoOutputPath) - const fps = await getVideoFileFPS(videoOutputPath) - inputVideoFile.set('size', stats.size) - inputVideoFile.set('fps', fps) - - await video.createTorrentAndSetInfoHash(inputVideoFile) - await inputVideoFile.save() + await onVideoFileTranscoding(video, inputVideoFile, videoTranscodedPath, videoOutputPath) } catch (err) { // Auto destruction... video.destroy().catch(err => logger.error('Cannot destruct video after transcoding failure.', { err })) @@ -52,8 +54,12 @@ async function optimizeVideofile (video: VideoModel, inputVideoFileArg?: VideoFi } } +/** + * Transcode the original video file to a lower resolution. + */ async function transcodeOriginalVideofile (video: VideoModel, resolution: VideoResolution, isPortrait: boolean) { const videosDirectory = CONFIG.STORAGE.VIDEOS_DIR + const transcodeDirectory = CONFIG.STORAGE.TMP_DIR const extname = '.mp4' // We are sure it's x264 in mp4 because optimizeOriginalVideofile was already executed @@ -66,27 +72,49 @@ async function transcodeOriginalVideofile (video: VideoModel, resolution: VideoR videoId: video.id }) const videoOutputPath = join(CONFIG.STORAGE.VIDEOS_DIR, video.getVideoFilename(newVideoFile)) + const videoTranscodedPath = join(transcodeDirectory, video.getVideoFilename(newVideoFile)) const transcodeOptions = { + type: 'video' as 'video', inputPath: videoInputPath, - outputPath: videoOutputPath, + outputPath: videoTranscodedPath, resolution, isPortraitMode: isPortrait } await transcode(transcodeOptions) - const stats = await stat(videoOutputPath) - const fps = await getVideoFileFPS(videoOutputPath) + return onVideoFileTranscoding(video, newVideoFile, videoTranscodedPath, videoOutputPath) +} + +async function mergeAudioVideofile (video: VideoModel, resolution: VideoResolution) { + const videosDirectory = CONFIG.STORAGE.VIDEOS_DIR + const transcodeDirectory = CONFIG.STORAGE.TMP_DIR + const newExtname = '.mp4' + + const inputVideoFile = video.getOriginalFile() - newVideoFile.set('size', stats.size) - newVideoFile.set('fps', fps) + const audioInputPath = join(videosDirectory, video.getVideoFilename(video.getOriginalFile())) + const videoTranscodedPath = join(transcodeDirectory, video.id + '-transcoded' + newExtname) - await video.createTorrentAndSetInfoHash(newVideoFile) + const transcodeOptions = { + type: 'merge-audio' as 'merge-audio', + inputPath: video.getPreview().getPath(), + outputPath: videoTranscodedPath, + audioPath: audioInputPath, + resolution + } + + await transcode(transcodeOptions) - await newVideoFile.save() + await remove(audioInputPath) - video.VideoFiles.push(newVideoFile) + // Important to do this before getVideoFilename() to take in account the new file extension + inputVideoFile.extname = newExtname + + const videoOutputPath = video.getVideoFilePath(inputVideoFile) + + return onVideoFileTranscoding(video, inputVideoFile, videoTranscodedPath, videoOutputPath) } async function generateHlsPlaylist (video: VideoModel, resolution: VideoResolution, isPortraitMode: boolean) { @@ -97,6 +125,7 @@ async function generateHlsPlaylist (video: VideoModel, resolution: VideoResoluti const outputPath = join(baseHlsDirectory, VideoStreamingPlaylistModel.getHlsPlaylistFilename(resolution)) const transcodeOptions = { + type: 'hls' as 'hls', inputPath: videoInputPath, outputPath, resolution, @@ -125,8 +154,34 @@ async function generateHlsPlaylist (video: VideoModel, resolution: VideoResoluti }) } +// --------------------------------------------------------------------------- + export { generateHlsPlaylist, optimizeVideofile, - transcodeOriginalVideofile + transcodeOriginalVideofile, + mergeAudioVideofile +} + +// --------------------------------------------------------------------------- + +async function onVideoFileTranscoding (video: VideoModel, videoFile: VideoFileModel, transcodingPath: string, outputPath: string) { + const stats = await stat(transcodingPath) + const fps = await getVideoFileFPS(transcodingPath) + + await move(transcodingPath, outputPath) + + videoFile.set('size', stats.size) + videoFile.set('fps', fps) + + await video.createTorrentAndSetInfoHash(videoFile) + + const updatedVideoFile = await videoFile.save() + + // Add it if this is a new created file + if (video.VideoFiles.some(f => f.id === videoFile.id) === false) { + video.VideoFiles.push(updatedVideoFile) + } + + return video }