1
0
Fork 0
mirror of https://github.com/Chocobozzz/PeerTube.git synced 2025-10-03 17:59:37 +02:00

Always specify s3 content type

This commit is contained in:
Chocobozzz 2025-05-26 11:08:47 +02:00
parent fb9d678f7f
commit 4739b117e8
No known key found for this signature in database
GPG key ID: 583A612D890159BE
7 changed files with 57 additions and 36 deletions

View file

@ -1368,7 +1368,7 @@ function buildVideoMimetypeExt () {
// The standard video format used by many Sony and Panasonic HD camcorders. // The standard video format used by many Sony and Panasonic HD camcorders.
// It is also used for storing high definition video on Blu-ray discs. // It is also used for storing high definition video on Blu-ray discs.
'video/mp2t': '.mts', 'video/mp2t': [ '.mts', 'ts' ],
'video/vnd.dlna.mpeg-tts': '.mts', 'video/vnd.dlna.mpeg-tts': '.mts',
'video/m2ts': '.m2ts', 'video/m2ts': '.m2ts',

View file

@ -144,8 +144,7 @@ function updateMasterHLSPlaylist (video: MVideo, playlistArg: MStreamingPlaylist
playlist.playlistUrl = await storeHLSFileFromContent({ playlist.playlistUrl = await storeHLSFileFromContent({
playlist, playlist,
pathOrFilename: playlist.playlistFilename, pathOrFilename: playlist.playlistFilename,
content: masterPlaylistContent, content: masterPlaylistContent
contentType: 'application/x-mpegurl; charset=utf-8'
}) })
logger.info(`Updated master playlist file of video ${video.uuid} to object storage ${playlist.playlistUrl}`, lTags(video.uuid)) logger.info(`Updated master playlist file of video ${video.uuid} to object storage ${playlist.playlistUrl}`, lTags(video.uuid))
@ -202,8 +201,7 @@ function updateSha256VODSegments (video: MVideo, playlistArg: MStreamingPlaylist
playlist.segmentsSha256Url = await storeHLSFileFromContent({ playlist.segmentsSha256Url = await storeHLSFileFromContent({
playlist, playlist,
pathOrFilename: playlist.segmentsSha256Filename, pathOrFilename: playlist.segmentsSha256Filename,
content: JSON.stringify(json), content: JSON.stringify(json)
contentType: 'application/json; charset=utf-8'
}) })
} else { } else {
const outputPath = VideoPathManager.Instance.getFSHLSOutputPath(video, playlist.segmentsSha256Filename) const outputPath = VideoPathManager.Instance.getFSHLSOutputPath(video, playlist.segmentsSha256Filename)

View file

@ -122,8 +122,7 @@ async function moveCaptionFiles (captions: MVideoCaption[], hls: MStreamingPlayl
caption.m3u8Url = await storeHLSFileFromContent({ caption.m3u8Url = await storeHLSFileFromContent({
playlist: hls, playlist: hls,
pathOrFilename: caption.m3u8Filename, pathOrFilename: caption.m3u8Filename,
content, content
contentType: 'application/vnd.apple.mpegurl; charset=utf-8'
}) })
await caption.save() await caption.save()

View file

@ -229,8 +229,7 @@ class MuxingSession extends EventEmitter implements MuxingSession {
{ {
playlist: this.streamingPlaylist, playlist: this.streamingPlaylist,
pathOrFilename: this.streamingPlaylist.playlistFilename, pathOrFilename: this.streamingPlaylist.playlistFilename,
content: masterContent, content: masterContent
contentType: 'application/x-mpegurl; charset=utf-8'
} }
) )
@ -419,8 +418,7 @@ class MuxingSession extends EventEmitter implements MuxingSession {
storeHLSFileFromContent({ storeHLSFileFromContent({
playlist: this.streamingPlaylist, playlist: this.streamingPlaylist,
pathOrFilename: m3u8Path, pathOrFilename: m3u8Path,
content: filteredPlaylistContent, content: filteredPlaylistContent
contentType: 'application/x-mpegurl; charset=utf-8'
}) })
) )
} catch (err) { } catch (err) {

View file

@ -50,8 +50,7 @@ async function storeObject (options: {
objectStorageKey: string objectStorageKey: string
bucketInfo: BucketInfo bucketInfo: BucketInfo
isPrivate: boolean isPrivate: boolean
contentType: string
contentType?: string
}): Promise<string> { }): Promise<string> {
const { inputPath, objectStorageKey, bucketInfo, isPrivate, contentType } = options const { inputPath, objectStorageKey, bucketInfo, isPrivate, contentType } = options
@ -67,8 +66,7 @@ async function storeContent (options: {
objectStorageKey: string objectStorageKey: string
bucketInfo: BucketInfo bucketInfo: BucketInfo
isPrivate: boolean isPrivate: boolean
contentType: string
contentType?: string
}): Promise<string> { }): Promise<string> {
const { content, objectStorageKey, bucketInfo, isPrivate, contentType } = options const { content, objectStorageKey, bucketInfo, isPrivate, contentType } = options
@ -82,8 +80,7 @@ async function storeStream (options: {
objectStorageKey: string objectStorageKey: string
bucketInfo: BucketInfo bucketInfo: BucketInfo
isPrivate: boolean isPrivate: boolean
contentType: string
contentType?: string
}): Promise<string> { }): Promise<string> {
const { stream, objectStorageKey, bucketInfo, isPrivate, contentType } = options const { stream, objectStorageKey, bucketInfo, isPrivate, contentType } = options

View file

@ -9,7 +9,8 @@ export function storeUserExportFile (stream: Readable, userExport: MUserExport)
stream, stream,
objectStorageKey: generateUserExportObjectStorageKey(userExport.filename), objectStorageKey: generateUserExportObjectStorageKey(userExport.filename),
bucketInfo: CONFIG.OBJECT_STORAGE.USER_EXPORTS, bucketInfo: CONFIG.OBJECT_STORAGE.USER_EXPORTS,
isPrivate: true isPrivate: true,
contentType: 'application/zip'
}) })
} }

View file

@ -2,7 +2,7 @@ import { logger } from '@server/helpers/logger.js'
import { CONFIG } from '@server/initializers/config.js' import { CONFIG } from '@server/initializers/config.js'
import { MStreamingPlaylistVideo, MStreamingPlaylistVideoUUID, MVideo, MVideoCaption, MVideoFile } from '@server/types/models/index.js' import { MStreamingPlaylistVideo, MStreamingPlaylistVideoUUID, MVideo, MVideoCaption, MVideoFile } from '@server/types/models/index.js'
import { MVideoSource } from '@server/types/models/video/video-source.js' import { MVideoSource } from '@server/types/models/video/video-source.js'
import { basename, join } from 'path' import { basename, extname, join } from 'path'
import { getHLSDirectory } from '../paths.js' import { getHLSDirectory } from '../paths.js'
import { VideoPathManager } from '../video-path-manager.js' import { VideoPathManager } from '../video-path-manager.js'
import { import {
@ -25,6 +25,7 @@ import {
updateObjectACL, updateObjectACL,
updatePrefixACL updatePrefixACL
} from './shared/index.js' } from './shared/index.js'
import { MIMETYPES } from '@server/initializers/constants.js'
export function listHLSFileKeysOf (playlist: MStreamingPlaylistVideo) { export function listHLSFileKeysOf (playlist: MStreamingPlaylistVideo) {
return listKeysOfPrefix(generateHLSObjectBaseStorageKey(playlist), CONFIG.OBJECT_STORAGE.STREAMING_PLAYLISTS) return listKeysOfPrefix(generateHLSObjectBaseStorageKey(playlist), CONFIG.OBJECT_STORAGE.STREAMING_PLAYLISTS)
@ -37,35 +38,38 @@ export function storeHLSFileFromFilename (playlist: MStreamingPlaylistVideo, fil
inputPath: join(getHLSDirectory(playlist.Video), filename), inputPath: join(getHLSDirectory(playlist.Video), filename),
objectStorageKey: generateHLSObjectStorageKey(playlist, filename), objectStorageKey: generateHLSObjectStorageKey(playlist, filename),
bucketInfo: CONFIG.OBJECT_STORAGE.STREAMING_PLAYLISTS, bucketInfo: CONFIG.OBJECT_STORAGE.STREAMING_PLAYLISTS,
isPrivate: playlist.Video.hasPrivateStaticPath() isPrivate: playlist.Video.hasPrivateStaticPath(),
contentType: getObjectStorageContentType(filename)
}) })
} }
export function storeHLSFileFromPath (playlist: MStreamingPlaylistVideo, path: string) { export function storeHLSFileFromPath (playlist: MStreamingPlaylistVideo, path: string) {
const filename = basename(path)
return storeObject({ return storeObject({
inputPath: path, inputPath: path,
objectStorageKey: generateHLSObjectStorageKey(playlist, basename(path)), objectStorageKey: generateHLSObjectStorageKey(playlist, filename),
bucketInfo: CONFIG.OBJECT_STORAGE.STREAMING_PLAYLISTS, bucketInfo: CONFIG.OBJECT_STORAGE.STREAMING_PLAYLISTS,
isPrivate: playlist.Video.hasPrivateStaticPath() isPrivate: playlist.Video.hasPrivateStaticPath(),
contentType: getObjectStorageContentType(filename)
}) })
} }
export function storeHLSFileFromContent ( export function storeHLSFileFromContent (options: {
options: {
playlist: MStreamingPlaylistVideo playlist: MStreamingPlaylistVideo
pathOrFilename: string pathOrFilename: string
content: string content: string
contentType: string }) {
} const { playlist, pathOrFilename, content } = options
) {
const { playlist, pathOrFilename, content, contentType } = options const filename = basename(pathOrFilename)
return storeContent({ return storeContent({
content, content,
objectStorageKey: generateHLSObjectStorageKey(playlist, basename(pathOrFilename)), objectStorageKey: generateHLSObjectStorageKey(playlist, filename),
bucketInfo: CONFIG.OBJECT_STORAGE.STREAMING_PLAYLISTS, bucketInfo: CONFIG.OBJECT_STORAGE.STREAMING_PLAYLISTS,
isPrivate: playlist.Video.hasPrivateStaticPath(), isPrivate: playlist.Video.hasPrivateStaticPath(),
contentType contentType: getObjectStorageContentType(filename)
}) })
} }
@ -76,7 +80,8 @@ export function storeWebVideoFile (video: MVideo, file: MVideoFile) {
inputPath: VideoPathManager.Instance.getFSVideoFileOutputPath(video, file), inputPath: VideoPathManager.Instance.getFSVideoFileOutputPath(video, file),
objectStorageKey: generateWebVideoObjectStorageKey(file.filename), objectStorageKey: generateWebVideoObjectStorageKey(file.filename),
bucketInfo: CONFIG.OBJECT_STORAGE.WEB_VIDEOS, bucketInfo: CONFIG.OBJECT_STORAGE.WEB_VIDEOS,
isPrivate: video.hasPrivateStaticPath() isPrivate: video.hasPrivateStaticPath(),
contentType: getObjectStorageContentType(file.filename)
}) })
} }
@ -88,7 +93,7 @@ export function storeVideoCaption (inputPath: string, filename: string) {
objectStorageKey: generateCaptionObjectStorageKey(filename), objectStorageKey: generateCaptionObjectStorageKey(filename),
bucketInfo: CONFIG.OBJECT_STORAGE.CAPTIONS, bucketInfo: CONFIG.OBJECT_STORAGE.CAPTIONS,
isPrivate: false, isPrivate: false,
contentType: 'text/vtt; charset=UTF-8' contentType: getObjectStorageContentType(filename)
}) })
} }
@ -99,7 +104,8 @@ export function storeOriginalVideoFile (inputPath: string, filename: string) {
inputPath, inputPath,
objectStorageKey: generateOriginalVideoObjectStorageKey(filename), objectStorageKey: generateOriginalVideoObjectStorageKey(filename),
bucketInfo: CONFIG.OBJECT_STORAGE.ORIGINAL_VIDEO_FILES, bucketInfo: CONFIG.OBJECT_STORAGE.ORIGINAL_VIDEO_FILES,
isPrivate: true isPrivate: true,
contentType: getObjectStorageContentType(filename)
}) })
} }
@ -279,3 +285,25 @@ export function getCaptionReadStream (options: {
rangeHeader rangeHeader
}) })
} }
// ---------------------------------------------------------------------------
// Private
// ---------------------------------------------------------------------------
function getObjectStorageContentType (filename: string) {
if (filename.endsWith('.m3u8')) {
return 'application/x-mpegURL; charset=utf-8'
}
if (filename.endsWith('.json')) {
return 'application/json; charset=utf-8'
}
if (filename.endsWith('.vtt')) {
return 'text/vtt; charset=utf-8'
}
const ext = extname(filename).toLowerCase()
return MIMETYPES.VIDEO.EXT_MIMETYPE[ext] || MIMETYPES.AUDIO.EXT_MIMETYPE[ext]
}