Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[bugfix] determine mime-type to use during ffprobe evaluation stage, don't bother checking against file extension #3506

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ require (
codeberg.org/gruf/go-kv v1.6.5
codeberg.org/gruf/go-list v0.0.0-20240425093752-494db03d641f
codeberg.org/gruf/go-mempool v0.0.0-20240507125005-cef10d64a760
codeberg.org/gruf/go-mimetypes v1.2.0
codeberg.org/gruf/go-mutexes v1.5.1
codeberg.org/gruf/go-runners v1.6.3
codeberg.org/gruf/go-sched v1.2.4
Expand Down
2 changes: 0 additions & 2 deletions go.sum

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 6 additions & 6 deletions internal/api/client/instance/instancepatch_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ func (suite *InstancePatchTestSuite) TestInstancePatch1() {
"image/apng",
"audio/ogg",
"video/ogg",
"audio/x-m4a",
"audio/mp4",
"video/mp4",
"video/quicktime",
"audio/x-ms-wma",
Expand Down Expand Up @@ -261,7 +261,7 @@ func (suite *InstancePatchTestSuite) TestInstancePatch2() {
"image/apng",
"audio/ogg",
"video/ogg",
"audio/x-m4a",
"audio/mp4",
"video/mp4",
"video/quicktime",
"audio/x-ms-wma",
Expand Down Expand Up @@ -402,7 +402,7 @@ func (suite *InstancePatchTestSuite) TestInstancePatch3() {
"image/apng",
"audio/ogg",
"video/ogg",
"audio/x-m4a",
"audio/mp4",
"video/mp4",
"video/quicktime",
"audio/x-ms-wma",
Expand Down Expand Up @@ -594,7 +594,7 @@ func (suite *InstancePatchTestSuite) TestInstancePatch6() {
"image/apng",
"audio/ogg",
"video/ogg",
"audio/x-m4a",
"audio/mp4",
"video/mp4",
"video/quicktime",
"audio/x-ms-wma",
Expand Down Expand Up @@ -757,7 +757,7 @@ func (suite *InstancePatchTestSuite) TestInstancePatch8() {
"image/apng",
"audio/ogg",
"video/ogg",
"audio/x-m4a",
"audio/mp4",
"video/mp4",
"video/quicktime",
"audio/x-ms-wma",
Expand Down Expand Up @@ -939,7 +939,7 @@ func (suite *InstancePatchTestSuite) TestInstancePatch9() {
"image/apng",
"audio/ogg",
"video/ogg",
"audio/x-m4a",
"audio/mp4",
"video/mp4",
"video/quicktime",
"audio/x-ms-wma",
Expand Down
75 changes: 48 additions & 27 deletions internal/media/ffmpeg.go
Original file line number Diff line number Diff line change
Expand Up @@ -323,70 +323,85 @@ type videoStream struct {
//
// Note the checks for (len(res.video) > 0) may catch some audio files with embedded
// album art as video, but i blame that on the hellscape that is media filetypes.
//
// TODO: we can update this code to also return a mimetype and avoid later parsing!
func (res *result) GetFileType() (gtsmodel.FileType, string) {
func (res *result) GetFileType() (gtsmodel.FileType, string, string) {
switch res.format {
case "mpeg":
return gtsmodel.FileTypeVideo, "mpeg"
return gtsmodel.FileTypeVideo,
"video/mpeg", "mpeg"
case "mjpeg":
return gtsmodel.FileTypeVideo, "mjpeg"
return gtsmodel.FileTypeVideo,
"video/x-motion-jpeg", "mjpeg"
case "mov,mp4,m4a,3gp,3g2,mj2":
switch {
case len(res.video) > 0:
if len(res.audio) == 0 &&
res.duration <= 30 {
// Short, soundless
// video file aka gifv.
return gtsmodel.FileTypeGifv, "mp4"
return gtsmodel.FileTypeGifv,
"video/mp4", "mp4"
} else {
// Video file (with or without audio).
return gtsmodel.FileTypeVideo, "mp4"
return gtsmodel.FileTypeVideo,
"video/mp4", "mp4"
}
case len(res.audio) > 0 &&
res.audio[0].codec == "aac":
// m4a only supports [aac] audio.
return gtsmodel.FileTypeAudio, "m4a"
return gtsmodel.FileTypeAudio,
"audio/mp4", "m4a"
}
case "apng":
return gtsmodel.FileTypeImage, "apng"
return gtsmodel.FileTypeImage,
"image/apng", "apng"
case "png_pipe":
return gtsmodel.FileTypeImage, "png"
return gtsmodel.FileTypeImage,
"image/png", "png"
case "image2", "image2pipe", "jpeg_pipe":
return gtsmodel.FileTypeImage, "jpeg"
return gtsmodel.FileTypeImage,
"image/jpeg", "jpeg"
case "webp", "webp_pipe":
return gtsmodel.FileTypeImage, "webp"
return gtsmodel.FileTypeImage,
"image/webp", "webp"
case "gif":
return gtsmodel.FileTypeImage, "gif"
return gtsmodel.FileTypeImage,
"image/gif", "gif"
case "mp3":
if len(res.audio) > 0 {
switch res.audio[0].codec {
case "mp2":
return gtsmodel.FileTypeAudio, "mp2"
return gtsmodel.FileTypeAudio,
"audio/mp2", "mp2"
case "mp3":
return gtsmodel.FileTypeAudio, "mp3"
return gtsmodel.FileTypeAudio,
"audio/mp3", "mp3"
}
}
case "asf":
switch {
case len(res.video) > 0:
return gtsmodel.FileTypeVideo, "wmv"
return gtsmodel.FileTypeVideo,
"video/x-ms-wmv", "wmv"
case len(res.audio) > 0:
return gtsmodel.FileTypeAudio, "wma"
return gtsmodel.FileTypeAudio,
"audio/x-ms-wma", "wma"
}
case "ogg":
if len(res.video) > 0 {
switch res.video[0].codec {
case "theora", "dirac": // daala, tarkin
return gtsmodel.FileTypeVideo, "ogv"
return gtsmodel.FileTypeVideo,
"video/ogg", "ogv"
}
}
if len(res.audio) > 0 {
switch res.audio[0].codec {
case "opus", "libopus":
return gtsmodel.FileTypeAudio, "opus"
return gtsmodel.FileTypeAudio,
"audio/opus", "opus"
default:
return gtsmodel.FileTypeAudio, "ogg"
return gtsmodel.FileTypeAudio,
"audio/ogg", "ogg"
}
}
case "matroska,webm":
Expand All @@ -411,21 +426,27 @@ func (res *result) GetFileType() (gtsmodel.FileType, string) {
}

if isWebm {
// Check for valid webm codec config.
return gtsmodel.FileTypeVideo, "webm"
// Check valid webm codec config.
return gtsmodel.FileTypeVideo,
"video/webm", "webm"
}

// All else falls under generic mkv.
return gtsmodel.FileTypeVideo, "mkv"
return gtsmodel.FileTypeVideo,
"video/x-matroska", "mkv"
case len(res.audio) > 0:
return gtsmodel.FileTypeAudio, "mka"
return gtsmodel.FileTypeAudio,
"audio/x-matroska", "mka"
}
case "avi":
return gtsmodel.FileTypeVideo, "avi"
return gtsmodel.FileTypeVideo,
"video/x-msvideo", "avi"
case "flac":
return gtsmodel.FileTypeAudio, "flac"
return gtsmodel.FileTypeAudio,
"audio/flac", "flac"
}
return gtsmodel.FileTypeUnknown, res.format
return gtsmodel.FileTypeUnknown,
"", res.format
}

// ImageMeta extracts image metadata contained within ffprobe'd media result streams.
Expand Down
2 changes: 1 addition & 1 deletion internal/media/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ var SupportedMIMETypes = []string{
"video/ogg", // .ogv

// mpeg4 types
"audio/x-m4a", // .m4a
"audio/mp4", // .m4a
"video/mp4", // .mp4
"video/quicktime", // .mov

Expand Down
2 changes: 1 addition & 1 deletion internal/media/manager_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -664,7 +664,7 @@ func (suite *ManagerTestSuite) TestOpusProcess() {
Duration: util.Ptr(float32(122.10006)),
Bitrate: util.Ptr(uint64(116426)),
}, attachment.FileMeta.Original)
suite.Equal("audio/ogg", attachment.File.ContentType)
suite.Equal("audio/opus", attachment.File.ContentType)
suite.Equal(1776956, attachment.File.FileSize)
suite.Empty(attachment.Blurhash)

Expand Down
9 changes: 3 additions & 6 deletions internal/media/processingemoji.go
Original file line number Diff line number Diff line change
Expand Up @@ -163,9 +163,10 @@ func (p *ProcessingEmoji) store(ctx context.Context) error {
}

var ext string
var fileType gtsmodel.FileType

// Get type from ffprobe format data.
fileType, ext := result.GetFileType()
// Get abstract file type, mimetype and ext from ffprobe data.
fileType, p.emoji.ImageContentType, ext = result.GetFileType()
if fileType != gtsmodel.FileTypeImage {
return gtserror.Newf("unsupported emoji filetype: %s (%s)", fileType, ext)
}
Expand Down Expand Up @@ -216,10 +217,6 @@ func (p *ProcessingEmoji) store(ctx context.Context) error {
"png",
)

// Get mimetype for the file container
// type, falling back to generic data.
p.emoji.ImageContentType = getMimeType(ext)

// Set the known emoji static content type.
p.emoji.ImageStaticContentType = "image/png"

Expand Down
20 changes: 8 additions & 12 deletions internal/media/processingmedia.go
Original file line number Diff line number Diff line change
Expand Up @@ -186,8 +186,8 @@ func (p *ProcessingMedia) store(ctx context.Context) error {
p.media.FileMeta.Original.Duration = util.PtrIf(float32(result.duration))
p.media.FileMeta.Original.Bitrate = util.PtrIf(result.bitrate)

// Set media type from ffprobe format data.
p.media.Type, ext = result.GetFileType()
// Set generic media type and mimetype from ffprobe format data.
p.media.Type, p.media.File.ContentType, ext = result.GetFileType()

// Add file extension to path.
newpath := temppath + "." + ext
Expand Down Expand Up @@ -236,10 +236,10 @@ func (p *ProcessingMedia) store(ctx context.Context) error {

// Determine if blurhash needs generating.
needBlurhash := (p.media.Blurhash == "")
var newBlurhash string
var newBlurhash, mimeType string

// Generate thumbnail, and new blurhash if need from media.
thumbpath, newBlurhash, err = generateThumb(ctx, temppath,
// Generate thumbnail, and new blurhash if needed from temp media.
thumbpath, mimeType, newBlurhash, err = generateThumb(ctx, temppath,
thumbWidth,
thumbHeight,
result.orientation,
Expand All @@ -250,6 +250,9 @@ func (p *ProcessingMedia) store(ctx context.Context) error {
return gtserror.Newf("error generating image thumb: %w", err)
}

// Set generated thumbnail's mimetype.
p.media.Thumbnail.ContentType = mimeType

if needBlurhash {
// Set newly determined blurhash.
p.media.Blurhash = newBlurhash
Expand All @@ -265,10 +268,6 @@ func (p *ProcessingMedia) store(ctx context.Context) error {
ext,
)

// Get mimetype for the file container
// type, falling back to generic data.
p.media.File.ContentType = getMimeType(ext)

// Copy temporary file into storage at path.
filesz, err := p.mgr.state.Storage.PutFile(ctx,
p.media.File.Path,
Expand All @@ -295,9 +294,6 @@ func (p *ProcessingMedia) store(ctx context.Context) error {
thumbExt,
)

// Determine thumbnail content-type from thumb ext.
p.media.Thumbnail.ContentType = getMimeType(thumbExt)

// Copy thumbnail file into storage at path.
thumbsz, err := p.mgr.state.Storage.PutFile(ctx,
p.media.Thumbnail.Path,
Expand Down
Loading