1 import { FfprobeData } from 'fluent-ffmpeg'
2 import { logger } from '@server/helpers/logger'
3 import { VideoFileModel } from '@server/models/video/video-file'
4 import { MVideoWithAllFiles } from '@server/types/models'
5 import { getLowercaseExtension } from '@shared/core-utils'
6 import { getFileSize } from '@shared/extra-utils'
7 import { ffprobePromise, getVideoStreamDimensionsInfo, getVideoStreamFPS, isAudioFile } from '@shared/ffmpeg'
8 import { VideoFileMetadata, VideoResolution } from '@shared/models'
9 import { lTags } from './object-storage/shared'
10 import { generateHLSVideoFilename, generateWebTorrentVideoFilename } from './paths'
12 async function buildNewFile (options: {
14 mode: 'web-video' | 'hls'
16 const { path, mode } = options
18 const probe = await ffprobePromise(path)
19 const size = await getFileSize(path)
21 const videoFile = new VideoFileModel({
22 extname: getLowercaseExtension(path),
24 metadata: await buildFileMetadata(path, probe)
27 if (await isAudioFile(path, probe)) {
28 videoFile.resolution = VideoResolution.H_NOVIDEO
30 videoFile.fps = await getVideoStreamFPS(path, probe)
31 videoFile.resolution = (await getVideoStreamDimensionsInfo(path, probe)).resolution
34 videoFile.filename = mode === 'web-video'
35 ? generateWebTorrentVideoFilename(videoFile.resolution, videoFile.extname)
36 : generateHLSVideoFilename(videoFile.resolution)
41 // ---------------------------------------------------------------------------
43 async function removeHLSPlaylist (video: MVideoWithAllFiles) {
44 const hls = video.getHLSPlaylist()
47 await video.removeStreamingPlaylistFiles(hls)
50 video.VideoStreamingPlaylists = video.VideoStreamingPlaylists.filter(p => p.id !== hls.id)
53 async function removeHLSFile (video: MVideoWithAllFiles, fileToDeleteId: number) {
54 logger.info('Deleting HLS file %d of %s.', fileToDeleteId, video.url, lTags(video.uuid))
56 const hls = video.getHLSPlaylist()
57 const files = hls.VideoFiles
59 if (files.length === 1) {
60 await removeHLSPlaylist(video)
64 const toDelete = files.find(f => f.id === fileToDeleteId)
65 await video.removeStreamingPlaylistVideoFile(video.getHLSPlaylist(), toDelete)
66 await toDelete.destroy()
68 hls.VideoFiles = hls.VideoFiles.filter(f => f.id !== toDelete.id)
73 // ---------------------------------------------------------------------------
75 async function removeAllWebTorrentFiles (video: MVideoWithAllFiles) {
76 for (const file of video.VideoFiles) {
77 await video.removeWebTorrentFile(file)
86 async function removeWebTorrentFile (video: MVideoWithAllFiles, fileToDeleteId: number) {
87 const files = video.VideoFiles
89 if (files.length === 1) {
90 return removeAllWebTorrentFiles(video)
93 const toDelete = files.find(f => f.id === fileToDeleteId)
94 await video.removeWebTorrentFile(toDelete)
95 await toDelete.destroy()
97 video.VideoFiles = files.filter(f => f.id !== toDelete.id)
102 // ---------------------------------------------------------------------------
104 async function buildFileMetadata (path: string, existingProbe?: FfprobeData) {
105 const metadata = existingProbe || await ffprobePromise(path)
107 return new VideoFileMetadata(metadata)
110 // ---------------------------------------------------------------------------
117 removeAllWebTorrentFiles,
118 removeWebTorrentFile,