diff options
Diffstat (limited to 'server/lib')
-rw-r--r-- | server/lib/job-queue/handlers/video-live-ending.ts | 12 | ||||
-rw-r--r-- | server/lib/job-queue/handlers/video-transcoding.ts | 23 | ||||
-rw-r--r-- | server/lib/video.ts | 28 |
3 files changed, 39 insertions, 24 deletions
diff --git a/server/lib/job-queue/handlers/video-live-ending.ts b/server/lib/job-queue/handlers/video-live-ending.ts index cd5bb1d1c..32eeff4d1 100644 --- a/server/lib/job-queue/handlers/video-live-ending.ts +++ b/server/lib/job-queue/handlers/video-live-ending.ts | |||
@@ -1,7 +1,8 @@ | |||
1 | import * as Bull from 'bull' | 1 | import * as Bull from 'bull' |
2 | import { readdir, remove } from 'fs-extra' | 2 | import { readdir, remove } from 'fs-extra' |
3 | import { join } from 'path' | 3 | import { join } from 'path' |
4 | import { getVideoFileResolution, hlsPlaylistToFragmentedMP4 } from '@server/helpers/ffmpeg-utils' | 4 | import { getDurationFromVideoFile, getVideoFileResolution, hlsPlaylistToFragmentedMP4 } from '@server/helpers/ffmpeg-utils' |
5 | import { publishAndFederateIfNeeded } from '@server/lib/video' | ||
5 | import { getHLSDirectory } from '@server/lib/video-paths' | 6 | import { getHLSDirectory } from '@server/lib/video-paths' |
6 | import { generateHlsPlaylist } from '@server/lib/video-transcoding' | 7 | import { generateHlsPlaylist } from '@server/lib/video-transcoding' |
7 | import { VideoModel } from '@server/models/video/video' | 8 | import { VideoModel } from '@server/models/video/video' |
@@ -44,6 +45,7 @@ async function saveLive (video: MVideo, live: MVideoLive) { | |||
44 | 45 | ||
45 | const playlistFiles = files.filter(f => f.endsWith('.m3u8') && f !== 'master.m3u8') | 46 | const playlistFiles = files.filter(f => f.endsWith('.m3u8') && f !== 'master.m3u8') |
46 | const resolutions: number[] = [] | 47 | const resolutions: number[] = [] |
48 | let duration: number | ||
47 | 49 | ||
48 | for (const playlistFile of playlistFiles) { | 50 | for (const playlistFile of playlistFiles) { |
49 | const playlistPath = join(hlsDirectory, playlistFile) | 51 | const playlistPath = join(hlsDirectory, playlistFile) |
@@ -58,6 +60,10 @@ async function saveLive (video: MVideo, live: MVideoLive) { | |||
58 | const segmentFiles = files.filter(f => f.startsWith(shouldStartWith) && f.endsWith('.ts')) | 60 | const segmentFiles = files.filter(f => f.startsWith(shouldStartWith) && f.endsWith('.ts')) |
59 | await hlsPlaylistToFragmentedMP4(hlsDirectory, segmentFiles, mp4TmpName) | 61 | await hlsPlaylistToFragmentedMP4(hlsDirectory, segmentFiles, mp4TmpName) |
60 | 62 | ||
63 | if (!duration) { | ||
64 | duration = await getDurationFromVideoFile(mp4TmpName) | ||
65 | } | ||
66 | |||
61 | resolutions.push(videoFileResolution) | 67 | resolutions.push(videoFileResolution) |
62 | } | 68 | } |
63 | 69 | ||
@@ -67,6 +73,8 @@ async function saveLive (video: MVideo, live: MVideoLive) { | |||
67 | 73 | ||
68 | video.isLive = false | 74 | video.isLive = false |
69 | video.state = VideoState.TO_TRANSCODE | 75 | video.state = VideoState.TO_TRANSCODE |
76 | video.duration = duration | ||
77 | |||
70 | await video.save() | 78 | await video.save() |
71 | 79 | ||
72 | const videoWithFiles = await VideoModel.loadWithFiles(video.id) | 80 | const videoWithFiles = await VideoModel.loadWithFiles(video.id) |
@@ -86,6 +94,8 @@ async function saveLive (video: MVideo, live: MVideoLive) { | |||
86 | 94 | ||
87 | video.state = VideoState.PUBLISHED | 95 | video.state = VideoState.PUBLISHED |
88 | await video.save() | 96 | await video.save() |
97 | |||
98 | await publishAndFederateIfNeeded(video) | ||
89 | } | 99 | } |
90 | 100 | ||
91 | async function cleanupLive (video: MVideo, streamingPlaylist: MStreamingPlaylist) { | 101 | async function cleanupLive (video: MVideo, streamingPlaylist: MStreamingPlaylist) { |
diff --git a/server/lib/job-queue/handlers/video-transcoding.ts b/server/lib/job-queue/handlers/video-transcoding.ts index 2aebc29f7..843a9f1b5 100644 --- a/server/lib/job-queue/handlers/video-transcoding.ts +++ b/server/lib/job-queue/handlers/video-transcoding.ts | |||
@@ -1,4 +1,5 @@ | |||
1 | import * as Bull from 'bull' | 1 | import * as Bull from 'bull' |
2 | import { publishAndFederateIfNeeded } from '@server/lib/video' | ||
2 | import { getVideoFilePath } from '@server/lib/video-paths' | 3 | import { getVideoFilePath } from '@server/lib/video-paths' |
3 | import { MVideoFullLight, MVideoUUID, MVideoWithFile } from '@server/types/models' | 4 | import { MVideoFullLight, MVideoUUID, MVideoWithFile } from '@server/types/models' |
4 | import { | 5 | import { |
@@ -174,25 +175,3 @@ function createHlsJobIfEnabled (payload?: { videoUUID: string, resolution: numbe | |||
174 | return JobQueue.Instance.createJob({ type: 'video-transcoding', payload: hlsTranscodingPayload }) | 175 | return JobQueue.Instance.createJob({ type: 'video-transcoding', payload: hlsTranscodingPayload }) |
175 | } | 176 | } |
176 | } | 177 | } |
177 | |||
178 | async function publishAndFederateIfNeeded (video: MVideoUUID) { | ||
179 | const { videoDatabase, videoPublished } = await sequelizeTypescript.transaction(async t => { | ||
180 | // Maybe the video changed in database, refresh it | ||
181 | const videoDatabase = await VideoModel.loadAndPopulateAccountAndServerAndTags(video.uuid, t) | ||
182 | // Video does not exist anymore | ||
183 | if (!videoDatabase) return undefined | ||
184 | |||
185 | // We transcoded the video file in another format, now we can publish it | ||
186 | const videoPublished = await videoDatabase.publishIfNeededAndSave(t) | ||
187 | |||
188 | // If the video was not published, we consider it is a new one for other instances | ||
189 | await federateVideoIfNeeded(videoDatabase, videoPublished, t) | ||
190 | |||
191 | return { videoDatabase, videoPublished } | ||
192 | }) | ||
193 | |||
194 | if (videoPublished) { | ||
195 | Notifier.Instance.notifyOnNewVideoIfNeeded(videoDatabase) | ||
196 | Notifier.Instance.notifyOnVideoPublishedAfterTranscoding(videoDatabase) | ||
197 | } | ||
198 | } | ||
diff --git a/server/lib/video.ts b/server/lib/video.ts index 6df41e6cd..81b7c4159 100644 --- a/server/lib/video.ts +++ b/server/lib/video.ts | |||
@@ -1,9 +1,12 @@ | |||
1 | import { Transaction } from 'sequelize/types' | 1 | import { Transaction } from 'sequelize/types' |
2 | import { sequelizeTypescript } from '@server/initializers/database' | ||
2 | import { TagModel } from '@server/models/video/tag' | 3 | import { TagModel } from '@server/models/video/tag' |
3 | import { VideoModel } from '@server/models/video/video' | 4 | import { VideoModel } from '@server/models/video/video' |
4 | import { FilteredModelAttributes } from '@server/types' | 5 | import { FilteredModelAttributes } from '@server/types' |
5 | import { MTag, MThumbnail, MVideoTag, MVideoThumbnail } from '@server/types/models' | 6 | import { MTag, MThumbnail, MVideoTag, MVideoThumbnail, MVideoUUID } from '@server/types/models' |
6 | import { ThumbnailType, VideoCreate, VideoPrivacy } from '@shared/models' | 7 | import { ThumbnailType, VideoCreate, VideoPrivacy } from '@shared/models' |
8 | import { federateVideoIfNeeded } from './activitypub/videos' | ||
9 | import { Notifier } from './notifier' | ||
7 | import { createVideoMiniatureFromExisting } from './thumbnail' | 10 | import { createVideoMiniatureFromExisting } from './thumbnail' |
8 | 11 | ||
9 | function buildLocalVideoFromReq (videoInfo: VideoCreate, channelId: number): FilteredModelAttributes<VideoModel> { | 12 | function buildLocalVideoFromReq (videoInfo: VideoCreate, channelId: number): FilteredModelAttributes<VideoModel> { |
@@ -78,10 +81,33 @@ async function setVideoTags (options: { | |||
78 | } | 81 | } |
79 | } | 82 | } |
80 | 83 | ||
84 | async function publishAndFederateIfNeeded (video: MVideoUUID) { | ||
85 | const { videoDatabase, videoPublished } = await sequelizeTypescript.transaction(async t => { | ||
86 | // Maybe the video changed in database, refresh it | ||
87 | const videoDatabase = await VideoModel.loadAndPopulateAccountAndServerAndTags(video.uuid, t) | ||
88 | // Video does not exist anymore | ||
89 | if (!videoDatabase) return undefined | ||
90 | |||
91 | // We transcoded the video file in another format, now we can publish it | ||
92 | const videoPublished = await videoDatabase.publishIfNeededAndSave(t) | ||
93 | |||
94 | // If the video was not published, we consider it is a new one for other instances | ||
95 | await federateVideoIfNeeded(videoDatabase, videoPublished, t) | ||
96 | |||
97 | return { videoDatabase, videoPublished } | ||
98 | }) | ||
99 | |||
100 | if (videoPublished) { | ||
101 | Notifier.Instance.notifyOnNewVideoIfNeeded(videoDatabase) | ||
102 | Notifier.Instance.notifyOnVideoPublishedAfterTranscoding(videoDatabase) | ||
103 | } | ||
104 | } | ||
105 | |||
81 | // --------------------------------------------------------------------------- | 106 | // --------------------------------------------------------------------------- |
82 | 107 | ||
83 | export { | 108 | export { |
84 | buildLocalVideoFromReq, | 109 | buildLocalVideoFromReq, |
110 | publishAndFederateIfNeeded, | ||
85 | buildVideoThumbnailsFromReq, | 111 | buildVideoThumbnailsFromReq, |
86 | setVideoTags | 112 | setVideoTags |
87 | } | 113 | } |