Skip to content

Convert video to playable format if ffmpeg installed#2003

Merged
freddyaboulton merged 11 commits into
mainfrom
convert-video-to-playable-codecs
Aug 16, 2022
Merged

Convert video to playable format if ffmpeg installed#2003
freddyaboulton merged 11 commits into
mainfrom
convert-video-to-playable-codecs

Conversation

@freddyaboulton
Copy link
Copy Markdown
Collaborator

@freddyaboulton freddyaboulton commented Aug 11, 2022

Description

Fixes #1970
Fixes #1990
Fixes #1972

In summary, I added video_is_playable util function to determine if a video can be played in the browser and convert_video_to_playable_mp4 in the event that the video is not playable. The rest are just unit tests.

I also added white_noise_vid_not_playable which is a reproducer of the original problem listed in one of the issues.

Checklist:

  • I have performed a self-review of my own code
  • My code follows the style guidelines of this project
  • I have commented my code in hard-to-understand areas
  • I have made corresponding changes to the documentation
  • I have added tests that prove my fix is effective or that my feature works
  • New and existing unit tests pass locally with my changes

@freddyaboulton freddyaboulton force-pushed the convert-video-to-playable-codecs branch from e55c4a8 to 459d485 Compare August 11, 2022 21:41
assert y.dtype == x.dtype


def test_video_has_playable_codecs(test_file_dir):
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

I added some files so that we can test positive and negative cases. I know increasing the repo size is a concern but I think testing the logic is worth adding the couple hundred kb

Comment thread gradio/components.py
Comment thread gradio/components.py
@freddyaboulton freddyaboulton marked this pull request as ready for review August 12, 2022 15:48
def video_is_playable(video_filepath: str) -> bool:
"""Determines if a video is playable in the browser.

A video is playable if it has a playable container and codec.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This is true all across major browsers?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

I believe so! Will confirm

Comment thread gradio/processing_utils.py Outdated
(".webm", "vp9"),
]
# If anything goes wrong, assume the video can be played to not convert downstream
except Exception:
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Nit: can we narrow the scope of this Exception?

Copy link
Copy Markdown

@lazarusking lazarusking Aug 27, 2022

Choose a reason for hiding this comment

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

I got a

video_codec= output["streams"][0]["codec_name"]
IndexError: list index out of range

The narrowed scope of the exception broke my application, it worked when I reverted back to "except Exception"

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Ah yikes that's good to know. I think it would be still be better to have a scope that includes IndexError as well, but WDYT @freddyaboulton?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

@lazarusking sorry to hear that! I originally used a wide exception because analyzing video streams with ffmpeg felt really unpredictable.

Can you provide a reproducer so we can dig in further? I’m curious why ffmpeg can’t find any video streams in your file, yet the video can be played in the browser if comment this out.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

My ffmpeg demo
It basically takes a file and converts it to the chosen format, allowing you the option to play it as video, audio or just as a file.
In the older gradio version, playing an audio as a video still works(when you toggle to video display option) but the new one doesn't find any video stream for such a case and just breaks.
It didn't account for "if anything goes wrong in this case".

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Thanks - I can put up a PR to also catch IndexError and KeyError!

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Thank you!

Comment thread gradio/processing_utils.py Outdated
(".webm", "vp9"),
]
# If anything goes wrong, assume the video can be played to not convert downstream
except Exception:
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Nit: can we narrow the scope of this Exception?

Comment thread gradio/processing_utils.py Outdated
"""
try:
container = pathlib.Path(video_filepath).suffix.lower()
output = subprocess.run(
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Instead of using subprocess, could we use ffmpeg.probe for cleaner code and better error handling: https://kkroening.github.io/ffmpeg-python/#ffmpeg.probe

Comment thread gradio/processing_utils.py Outdated
global_options="-y -loglevel quiet",
)
ff.run()
except:
Copy link
Copy Markdown
Member

@abidlabs abidlabs Aug 15, 2022

Choose a reason for hiding this comment

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

Same nit: is it possible to narrow the scope to ffmpeg.Error?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Yea good call!

Comment thread gradio/processing_utils.py
@abidlabs
Copy link
Copy Markdown
Member

I tried running the white_noise_vid_not_playable demo, and it isn't working for me. I see a completely black output:

image

Note that downloading the file works fine.

No Python logs except for the warning: UserWarning: Video does not have browser-compatible container or codec. Converting to mp4

On the JS side, I see: "Uncaught (in promise) DOMException: The element has no supported sources."

Tested on Chrome and Edge browsers on Windows.

@freddyaboulton
Copy link
Copy Markdown
Collaborator Author

@abidlabs Thanks for reviewing/running the demo! Let me dig into why it didn't work for you

@abidlabs
Copy link
Copy Markdown
Member

Working great now @freddyaboulton!

image

@freddyaboulton freddyaboulton force-pushed the convert-video-to-playable-codecs branch from 0247be3 to f3db84f Compare August 16, 2022 16:17
@github-actions
Copy link
Copy Markdown
Contributor

All the demos for this PR have been deployed at https://huggingface.co/spaces/gradio-pr-deploys/pr-2003-all-demos

@freddyaboulton freddyaboulton merged commit 75b5180 into main Aug 16, 2022
@freddyaboulton freddyaboulton deleted the convert-video-to-playable-codecs branch August 16, 2022 17:21
@lukasfolle
Copy link
Copy Markdown

In my hf space, the video plays nicely on Chrome and Firefox, but not on Safari. I use the .ogg video container and the theora codec.

Normally, I would expect a conversion to mp4, but this is not happening..
Any ideas @freddyaboulton @abidlabs?

@freddyaboulton
Copy link
Copy Markdown
Collaborator Author

Hi @lukasfolle ! Thanks for asking. Very cool space and I am also unable to see the video on my mac when using safari.

The conversion to mp4 may not be happening because .ogg is a playable video container but it has spotty support on safari: https://caniuse.com/?search=ogg

Maybe you can "force" the mp4 conversion by giving your file an mp4 extension and using a different video codec?

I think just changing the extension here to .mp4 should be enough?

https://huggingface.co/spaces/lfolle/LDM-SyntheticChestX-Ray/blob/main/create_video.py#L19

@lukasfolle
Copy link
Copy Markdown

lukasfolle commented Dec 9, 2022

Hi @freddyaboulton,

Thanks for your reply. I now switched to mp4 (h264) and it seems to only work on edge, firefox now shows a black window for me. Running locally it works for me..
Any idea whats going wrong here?

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.

Error displaying video generated by open-cv Issues when loading/outputting video Add information about available video codecs

4 participants