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'
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'
/**
? 'quick-transcode'
: 'video'
+ const resolution = toEven(inputVideoFile.resolution)
+
const transcodeOptions: TranscodeOptions = {
type: transcodeType,
availableEncoders: VideoTranscodingProfilesManager.Instance.getAvailableEncoders(),
profile: CONFIG.TRANSCODING.PROFILE,
- resolution: inputVideoFile.resolution,
+ resolution,
job
}
// 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)
const newVideoFile = new VideoFileModel({
resolution,
extname,
- filename: generateVideoFilename(video, false, resolution, extname),
+ filename: generateWebTorrentVideoFilename(resolution, extname),
size: 0,
videoId: video.id
})
// 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
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,
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)
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 })
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
}