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

Add mp4 support #1419

Merged
merged 16 commits into from
Feb 3, 2023
Merged

Add mp4 support #1419

merged 16 commits into from
Feb 3, 2023

Conversation

cryptoquick
Copy link
Contributor

@cryptoquick cryptoquick commented Jan 30, 2023

@cryptoquick
Copy link
Contributor Author

cryptoquick commented Jan 30, 2023

After running the server, I just realized why you don't like "illicit NFT" formats. I think you basically have to reindex, lol

@casey
Copy link
Collaborator

casey commented Jan 30, 2023

@cryptoquick I want to do a check that the client only allows H.264 in MP4 when it uploads. If you want to look into doing that feel free, I think there's an MP4 parsing crate somewhere, otherwise feel free to leave this open and I can add that later.

You shouldn't have to reindex, illicit content types are indexed just fine, it's just the frontent that doesn't show them. However, we did change the database schema on master, so that might be what you're running into.

@cryptoquick
Copy link
Contributor Author

@casey
Copy link
Collaborator

casey commented Jan 30, 2023

Yup, video/mp4 is an unsupported content type (not present in table in media.rs), so the server uses PreviewUnknownHtml when serving /preview, which is just an empty page.

We could add it to the media.rs table, but not give it a file extension. This would allow inscriptions with type video/mp4 to be previewed, but ord would still not allow publishing them, because files would have an unrecognized extension.

Then later when we check the codec in .mp4s when inscribing, we can add the .mp4 extension to the media table so that they can be inscribed without having to hack the client.

@casey
Copy link
Collaborator

casey commented Jan 30, 2023

See the route in server.rs for /preview. (I think it's just fn preview.)

src/media.rs Show resolved Hide resolved
Co-authored-by: Casey Rodarmor <casey@rodarmor.com>
@cryptoquick
Copy link
Contributor Author

What I saw in preview was really weird to me. Maybe good for testing? I couldn't figure out what it was for or how to use it.

Also, just so I don't assume, why the h264 requirement? Compatibility?

@casey
Copy link
Collaborator

casey commented Jan 30, 2023

Also, just so I don't assume, why the h264 requirement? Compatibility?

Yah, that's correct. Cross-browser compatibility of containers and codecs is really bad. The reasonable choices for good compatibility are H.264 in MP4 and VP8/VP9/AV1 in WebM. MP4 is containers used with many codecs, and many of those codecs are unsupported. In particular, MP4 is often used with HEVC, which both doesn't have great support (doesn't work in firefox for example) and is patent encumbered. WebM though, even though it's a container, not a codec, is almost always used with broadly supported codecs.

A user might preview a HEVC in MP4 inscription with their browser, but then find that many other browsers won't display it after publishing it.

@cryptoquick
Copy link
Contributor Author

It's looking like adding the codec check is actually gonna be pretty easy, I should have a commit for that soon.

Copy link
Collaborator

@casey casey left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some comments!

Comment on lines 47 to 57
let extension = path
.extension()
.ok_or_else(|| anyhow!("file must have extension"))?
.to_str()
.ok_or_else(|| anyhow!("unrecognized extension"))?;

if extension == "mp4" {
Media::check_mp4_codec(path)?;
}

let content_type = Media::content_type_for_extension(extension)?;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's move these three checks into Media::content_type_for_path, e.g. extract the extension, check the codecs, and then return the Media value.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good thinking! That'll be cleaner. I'll rename the method, and do as you suggested.

src/media.rs Outdated
#[test]
fn check_mp4_codec() {
assert!(
Media::check_mp4_codec(Path::new("bitcoin-pup.mp4")).is_ok(),
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could use a negative test too, to check that an MP4 with an unsupported video codec fails the check.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll look into it.

src/media.rs Outdated
Comment on lines 49 to 54
if let TrackType::Video = track.track_type()? {
if let MediaType::H264 = track.media_type()? {
return Ok(());
} else {
return Err(anyhow!("h264 format supported, only"));
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have no idea what can go into an MP4, but let's check all tracks, and also put the unsupported media type in the error message:

      if let TrackType::Video = track.track_type()? {
        let media_type = track.media_type()?;
        if let MediaType::H264 != media_type {
          return Err(anyhow!("Unsupported video codec, only H.264 is supported in MP4s: {media_type}"));
        }

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you look at the enums for either TrackType and MediaType, I believe this code will behave as expected... So long as any one of the video tracks doesn't contain something that isn't encoded as h264, it returns Ok, otherwise, it returns an error.

That said, it's a good suggestion to return the media type.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just realized, the code I had before had slightly different logic than when I explained what I wanted... I'm gonna redo some of that logic also.

… mp4 codec detection logic. Add negative mp4 test case.
@cryptoquick cryptoquick changed the title Add mp4 to supported media types. Add mp4 support Feb 1, 2023
@cryptoquick
Copy link
Contributor Author

@casey icymi, this pr is rfr

@casey casey enabled auto-merge (squash) February 3, 2023 03:49
@casey casey merged commit 0ded5d8 into ordinals:master Feb 3, 2023
@casey
Copy link
Collaborator

casey commented Feb 3, 2023

@cryptoquick Nice, thanks for the ping! I tweaked a little, just the tests. I moved the example files into examples/ with descriptive filenames, and split up the tests into two with descriptive names. Also sorted the media table, and fixed a test which broke because it was expecting only valid inscriptions in examples/. Hope you don't mind!

Thanks for this, vv nice addition ❤️

@cryptoquick cryptoquick deleted the mp4 branch February 4, 2023 09:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Consider supporting additional video format: H.264 codec in MP4 container
2 participants