mini_mime
mini_mime copied to clipboard
webm and wmv miscategorized as video instead of audio
Redmine uses mini_mime to determine whether an uploaded media file is an audio or a video file to decide whether to use a <audio> or <video> tag in the HTML.
Unfortunately, both *.webm and *.wmv files are "miscategorized" as audio by mini_mime:
https://github.com/discourse/mini_mime/blob/master/lib/db/ext_mime.db#L1048
webm audio/webm base64
https://github.com/discourse/mini_mime/blob/master/lib/db/ext_mime.db#L1064
wmv audio/x-ms-wmv base64
Though this isn't strictly wrong (webm is a container format for both audio and video; wmv is intended for video, but of course also can contain audio), it is IMO not what one would expect. In this case it's causing Redmine to attempt to play these kinds of video files with an <audio> tag, which forces users to download the files to actually see the video: https://www.redmine.org/issues/31553
For webm, this has been overridden in Redmine, but today I've stumbled over the same issue with wmv. I thought that MIME::Types solved this pretty elegantly by returning an array of matching MIME types, but apparently that library suffers from memory usage issues which led to Redmine replacing it with mini_mime.
I'm not sure what the best solution would be here. I'm pretty new to Ruby and all of these libraries, but from what I can gather, mini_mime uses MIME::Types internally to generate a list of extension -> MIME types mappings, and lets priority_compare decide which MIME type will win when there are multiple. But there is not real concept of "priority" in MIME::Types in the sense of that e.g. video/webm can have a higher priority than audio/webm. priority_compare essentially just simplifies the MIME types, and then compares them alphabetically. This means that audio will always win over video:
irb(main):005:0> MIME::Types.type_for('test.wmv').each { |m| pp m.simplified }; nil
"audio/x-ms-wmv"
"video/x-ms-wmv"
=> nil
IMO this is a fundamental problem which cannot be easily solved, and the proper fix would be to return multiple MIME types for a given extension (#25).
Fundamentally you are going to end up picking "one thing" so the interface of "please give me a mime type for X" is still correct imo.
I do support adding a clear interface for adding overrides provided it has zero cost when unused.
I am exploring improving extension priority to fix this sort of issue. See mime-types/ruby-mime-types#161. This is not going to be quick, and it may be a bit longer to get it in mini_mime, but since I implemented mime-types/mime-types-data#47, I might be able to get something that is testable sooner once I figure it out.
The tools for this are in process. I’m going to need to find some Ruby community volunteers to review the changes here, but the main changes are https://github.com/mime-types/mime-types-data/tree/priority-extensions and are supported https://github.com/mime-types/ruby-mime-types/tree/priority-extensions. The description of how this affects mini_mime is found in #44.
If you want wmv and webm to represent video, I will need an issue or PR on mime-types-data that recommends these changes. Since there’s almost no authority on this, it would not take much convincing, but I do want to see why we should skew things one way or another. In my experience, when I was using Windows, wmv were mostly audio files. I have no experience with webm files. IIRC, wmv aren’t backed by registered types, but webm are and the registrations for the types include webm as valid for both types.