]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blobdiff - server/lib/job-queue/handlers/video-live-ending.ts
Reload the video after waiting for the files lock
[github/Chocobozzz/PeerTube.git] / server / lib / job-queue / handlers / video-live-ending.ts
index 7dbffc955628e7575c404e4e33589d930c43a204..814f313a3bb8d946905bbbce3fb1ffba571e0d28 100644 (file)
@@ -1,21 +1,23 @@
 import { Job } from 'bullmq'
 import { readdir, remove } from 'fs-extra'
 import { join } from 'path'
-import { ffprobePromise, getAudioStream, getVideoStreamDimensionsInfo } from '@server/helpers/ffmpeg'
 import { getLocalVideoActivityPubUrl } from '@server/lib/activitypub/url'
 import { federateVideoIfNeeded } from '@server/lib/activitypub/videos'
 import { cleanupAndDestroyPermanentLive, cleanupTMPLiveFiles, cleanupUnsavedNormalLive } from '@server/lib/live'
 import { generateHLSMasterPlaylistFilename, generateHlsSha256SegmentsFilename, getLiveReplayBaseDirectory } from '@server/lib/paths'
 import { generateVideoMiniature } from '@server/lib/thumbnail'
-import { generateHlsPlaylistResolutionFromTS } from '@server/lib/transcoding/transcoding'
+import { generateHlsPlaylistResolutionFromTS } from '@server/lib/transcoding/hls-transcoding'
+import { VideoPathManager } from '@server/lib/video-path-manager'
 import { moveToNextState } from '@server/lib/video-state'
 import { VideoModel } from '@server/models/video/video'
 import { VideoBlacklistModel } from '@server/models/video/video-blacklist'
 import { VideoFileModel } from '@server/models/video/video-file'
 import { VideoLiveModel } from '@server/models/video/video-live'
+import { VideoLiveReplaySettingModel } from '@server/models/video/video-live-replay-setting'
 import { VideoLiveSessionModel } from '@server/models/video/video-live-session'
 import { VideoStreamingPlaylistModel } from '@server/models/video/video-streaming-playlist'
 import { MVideo, MVideoLive, MVideoLiveSession, MVideoWithAllFiles } from '@server/types/models'
+import { ffprobePromise, getAudioStream, getVideoStreamDimensionsInfo, getVideoStreamFPS } from '@shared/ffmpeg'
 import { ThumbnailType, VideoLiveEndingPayload, VideoState } from '@shared/models'
 import { logger, loggerTagsFactory } from '../../../helpers/logger'
 
@@ -59,7 +61,13 @@ async function processVideoLiveEnding (job: Job) {
     return cleanupLiveAndFederate({ permanentLive, video, streamingPlaylistId: payload.streamingPlaylistId })
   }
 
-  return replaceLiveByReplay({ video, liveSession, live, permanentLive, replayDirectory: payload.replayDirectory })
+  return replaceLiveByReplay({
+    video,
+    liveSession,
+    live,
+    permanentLive,
+    replayDirectory: payload.replayDirectory
+  })
 }
 
 // ---------------------------------------------------------------------------
@@ -78,6 +86,8 @@ async function saveReplayToExternalVideo (options: {
 }) {
   const { liveVideo, liveSession, publishedAt, replayDirectory } = options
 
+  const replaySettings = await VideoLiveReplaySettingModel.load(liveSession.replaySettingId)
+
   const replayVideo = new VideoModel({
     name: `${liveVideo.name} - ${new Date(publishedAt).toLocaleString()}`,
     isLive: false,
@@ -94,7 +104,7 @@ async function saveReplayToExternalVideo (options: {
     nsfw: liveVideo.nsfw,
     description: liveVideo.description,
     support: liveVideo.support,
-    privacy: liveVideo.privacy,
+    privacy: replaySettings.privacy,
     channelId: liveVideo.channelId
   }) as MVideoWithAllFiles
 
@@ -141,6 +151,7 @@ async function replaceLiveByReplay (options: {
 }) {
   const { video, liveSession, live, permanentLive, replayDirectory } = options
 
+  const replaySettings = await VideoLiveReplaySettingModel.load(liveSession.replaySettingId)
   const videoWithFiles = await VideoModel.loadFull(video.id)
   const hlsPlaylist = videoWithFiles.getHLSPlaylist()
 
@@ -149,6 +160,7 @@ async function replaceLiveByReplay (options: {
   await live.destroy()
 
   videoWithFiles.isLive = false
+  videoWithFiles.privacy = replaySettings.privacy
   videoWithFiles.waitTranscoding = true
   videoWithFiles.state = VideoState.TO_TRANSCODE
 
@@ -205,18 +217,30 @@ async function assignReplayFilesToVideo (options: {
   const concatenatedTsFiles = await readdir(replayDirectory)
 
   for (const concatenatedTsFile of concatenatedTsFiles) {
+    const inputFileMutexReleaser = await VideoPathManager.Instance.lockFiles(video.uuid)
+    await video.reload()
+
     const concatenatedTsFilePath = join(replayDirectory, concatenatedTsFile)
 
     const probe = await ffprobePromise(concatenatedTsFilePath)
     const { audioStream } = await getAudioStream(concatenatedTsFilePath, probe)
     const { resolution } = await getVideoStreamDimensionsInfo(concatenatedTsFilePath, probe)
+    const fps = await getVideoStreamFPS(concatenatedTsFilePath, probe)
+
+    try {
+      await generateHlsPlaylistResolutionFromTS({
+        video,
+        inputFileMutexReleaser,
+        concatenatedTsFilePath,
+        resolution,
+        fps,
+        isAAC: audioStream?.codec_name === 'aac'
+      })
+    } catch (err) {
+      logger.error('Cannot generate HLS playlist resolution from TS files.', { err })
+    }
 
-    await generateHlsPlaylistResolutionFromTS({
-      video,
-      concatenatedTsFilePath,
-      resolution,
-      isAAC: audioStream?.codec_name === 'aac'
-    })
+    inputFileMutexReleaser()
   }
 
   return video