]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blobdiff - server/lib/transcoding/video-transcoding.ts
Merge branch 'release/3.3.0' into develop
[github/Chocobozzz/PeerTube.git] / server / lib / transcoding / video-transcoding.ts
index 5df192575f1ea6548f8291ca703b133a400d199f..d2a556360afbdc0ca525f654c6b97bb45d6d2466 100644 (file)
@@ -1,6 +1,7 @@
 import { Job } from 'bull'
 import { copyFile, ensureDir, move, remove, stat } from 'fs-extra'
 import { basename, extname as extnameUtil, join } from 'path'
+import { toEven } from '@server/helpers/core-utils'
 import { createTorrentAndSetInfoHash } from '@server/helpers/webtorrent'
 import { MStreamingPlaylistFilesVideo, MVideoFile, MVideoFullLight } from '@server/types/models'
 import { VideoResolution } from '../../../shared/models/videos'
@@ -9,11 +10,18 @@ import { transcode, TranscodeOptions, TranscodeOptionsType } from '../../helpers
 import { canDoQuickTranscode, getDurationFromVideoFile, getMetadataFromFile, getVideoFileFPS } from '../../helpers/ffprobe-utils'
 import { logger } from '../../helpers/logger'
 import { CONFIG } from '../../initializers/config'
-import { HLS_STREAMING_PLAYLIST_DIRECTORY, P2P_MEDIA_LOADER_PEER_VERSION, WEBSERVER } from '../../initializers/constants'
+import { HLS_STREAMING_PLAYLIST_DIRECTORY, P2P_MEDIA_LOADER_PEER_VERSION } from '../../initializers/constants'
 import { VideoFileModel } from '../../models/video/video-file'
 import { VideoStreamingPlaylistModel } from '../../models/video/video-streaming-playlist'
 import { updateMasterHLSPlaylist, updateSha256VODSegments } from '../hls'
-import { generateVideoFilename, generateVideoStreamingPlaylistName, getVideoFilePath } from '../video-paths'
+import {
+  generateHLSMasterPlaylistFilename,
+  generateHlsSha256SegmentsFilename,
+  generateHLSVideoFilename,
+  generateWebTorrentVideoFilename,
+  getHlsResolutionPlaylistFilename,
+  getVideoFilePath
+} from '../video-paths'
 import { VideoTranscodingProfilesManager } from './video-transcoding-profiles'
 
 /**
@@ -35,6 +43,8 @@ async function optimizeOriginalVideofile (video: MVideoFullLight, inputVideoFile
     ? 'quick-transcode'
     : 'video'
 
+  const resolution = toEven(inputVideoFile.resolution)
+
   const transcodeOptions: TranscodeOptions = {
     type: transcodeType,
 
@@ -44,7 +54,7 @@ async function optimizeOriginalVideofile (video: MVideoFullLight, inputVideoFile
     availableEncoders: VideoTranscodingProfilesManager.Instance.getAvailableEncoders(),
     profile: CONFIG.TRANSCODING.PROFILE,
 
-    resolution: inputVideoFile.resolution,
+    resolution,
 
     job
   }
@@ -57,7 +67,7 @@ async function optimizeOriginalVideofile (video: MVideoFullLight, inputVideoFile
 
     // Important to do this before getVideoFilename() to take in account the new filename
     inputVideoFile.extname = newExtname
-    inputVideoFile.filename = generateVideoFilename(video, false, inputVideoFile.resolution, newExtname)
+    inputVideoFile.filename = generateWebTorrentVideoFilename(resolution, newExtname)
 
     const videoOutputPath = getVideoFilePath(video, inputVideoFile)
 
@@ -83,7 +93,7 @@ async function transcodeNewWebTorrentResolution (video: MVideoFullLight, resolut
   const newVideoFile = new VideoFileModel({
     resolution,
     extname,
-    filename: generateVideoFilename(video, false, resolution, extname),
+    filename: generateWebTorrentVideoFilename(resolution, extname),
     size: 0,
     videoId: video.id
   })
@@ -166,7 +176,7 @@ async function mergeAudioVideofile (video: MVideoFullLight, resolution: VideoRes
 
   // Important to do this before getVideoFilename() to take in account the new file extension
   inputVideoFile.extname = newExtname
-  inputVideoFile.filename = generateVideoFilename(video, false, inputVideoFile.resolution, newExtname)
+  inputVideoFile.filename = generateWebTorrentVideoFilename(inputVideoFile.resolution, newExtname)
 
   const videoOutputPath = getVideoFilePath(video, inputVideoFile)
   // ffmpeg generated a new video file, so update the video duration
@@ -268,15 +278,15 @@ async function generateHlsPlaylistCommon (options: {
   const videoTranscodedBasePath = join(transcodeDirectory, type)
   await ensureDir(videoTranscodedBasePath)
 
-  const videoFilename = generateVideoStreamingPlaylistName(video.uuid, resolution)
-  const playlistFilename = VideoStreamingPlaylistModel.getHlsPlaylistFilename(resolution)
-  const playlistFileTranscodePath = join(videoTranscodedBasePath, playlistFilename)
+  const videoFilename = generateHLSVideoFilename(resolution)
+  const resolutionPlaylistFilename = getHlsResolutionPlaylistFilename(videoFilename)
+  const resolutionPlaylistFileTranscodePath = join(videoTranscodedBasePath, resolutionPlaylistFilename)
 
   const transcodeOptions = {
     type,
 
     inputPath,
-    outputPath: playlistFileTranscodePath,
+    outputPath: resolutionPlaylistFileTranscodePath,
 
     availableEncoders: VideoTranscodingProfilesManager.Instance.getAvailableEncoders(),
     profile: CONFIG.TRANSCODING.PROFILE,
@@ -296,19 +306,23 @@ async function generateHlsPlaylistCommon (options: {
 
   await transcode(transcodeOptions)
 
-  const playlistUrl = WEBSERVER.URL + VideoStreamingPlaylistModel.getHlsMasterPlaylistStaticPath(video.uuid)
-
   // Create or update the playlist
-  const [ videoStreamingPlaylist ] = await VideoStreamingPlaylistModel.upsert({
-    videoId: video.id,
-    playlistUrl,
-    segmentsSha256Url: WEBSERVER.URL + VideoStreamingPlaylistModel.getHlsSha256SegmentsStaticPath(video.uuid, video.isLive),
-    p2pMediaLoaderInfohashes: [],
-    p2pMediaLoaderPeerVersion: P2P_MEDIA_LOADER_PEER_VERSION,
+  const playlist = await VideoStreamingPlaylistModel.loadOrGenerate(video)
+
+  if (!playlist.playlistFilename) {
+    playlist.playlistFilename = generateHLSMasterPlaylistFilename(video.isLive)
+  }
 
-    type: VideoStreamingPlaylistType.HLS
-  }, { returning: true }) as [ MStreamingPlaylistFilesVideo, boolean ]
-  videoStreamingPlaylist.Video = video
+  if (!playlist.segmentsSha256Filename) {
+    playlist.segmentsSha256Filename = generateHlsSha256SegmentsFilename(video.isLive)
+  }
+
+  playlist.p2pMediaLoaderInfohashes = []
+  playlist.p2pMediaLoaderPeerVersion = P2P_MEDIA_LOADER_PEER_VERSION
+
+  playlist.type = VideoStreamingPlaylistType.HLS
+
+  await playlist.save()
 
   // Build the new playlist file
   const extname = extnameUtil(videoFilename)
@@ -316,20 +330,20 @@ async function generateHlsPlaylistCommon (options: {
     resolution,
     extname,
     size: 0,
-    filename: generateVideoFilename(video, true, resolution, extname),
+    filename: videoFilename,
     fps: -1,
-    videoStreamingPlaylistId: videoStreamingPlaylist.id
+    videoStreamingPlaylistId: playlist.id
   })
 
-  const videoFilePath = getVideoFilePath(videoStreamingPlaylist, newVideoFile)
+  const videoFilePath = getVideoFilePath(playlist, newVideoFile)
 
   // Move files from tmp transcoded directory to the appropriate place
   const baseHlsDirectory = join(HLS_STREAMING_PLAYLIST_DIRECTORY, video.uuid)
   await ensureDir(baseHlsDirectory)
 
   // Move playlist file
-  const playlistPath = join(baseHlsDirectory, playlistFilename)
-  await move(playlistFileTranscodePath, playlistPath, { overwrite: true })
+  const resolutionPlaylistPath = join(baseHlsDirectory, resolutionPlaylistFilename)
+  await move(resolutionPlaylistFileTranscodePath, resolutionPlaylistPath, { overwrite: true })
   // Move video file
   await move(join(videoTranscodedBasePath, videoFilename), videoFilePath, { overwrite: true })
 
@@ -339,20 +353,20 @@ async function generateHlsPlaylistCommon (options: {
   newVideoFile.fps = await getVideoFileFPS(videoFilePath)
   newVideoFile.metadata = await getMetadataFromFile(videoFilePath)
 
-  await createTorrentAndSetInfoHash(videoStreamingPlaylist, newVideoFile)
+  await createTorrentAndSetInfoHash(playlist, newVideoFile)
 
   await VideoFileModel.customUpsert(newVideoFile, 'streaming-playlist', undefined)
-  videoStreamingPlaylist.VideoFiles = await videoStreamingPlaylist.$get('VideoFiles')
 
-  videoStreamingPlaylist.p2pMediaLoaderInfohashes = VideoStreamingPlaylistModel.buildP2PMediaLoaderInfoHashes(
-    playlistUrl, videoStreamingPlaylist.VideoFiles
-  )
-  await videoStreamingPlaylist.save()
+  const playlistWithFiles = playlist as MStreamingPlaylistFilesVideo
+  playlistWithFiles.VideoFiles = await playlist.$get('VideoFiles')
+  playlist.assignP2PMediaLoaderInfoHashes(video, playlistWithFiles.VideoFiles)
+
+  await playlist.save()
 
-  video.setHLSPlaylist(videoStreamingPlaylist)
+  video.setHLSPlaylist(playlist)
 
-  await updateMasterHLSPlaylist(video)
-  await updateSha256VODSegments(video)
+  await updateMasterHLSPlaylist(video, playlistWithFiles)
+  await updateSha256VODSegments(video, playlistWithFiles)
 
-  return playlistPath
+  return resolutionPlaylistPath
 }