-
Notifications
You must be signed in to change notification settings - Fork 140
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
How to extract video frame as imageData using webcodecs? #86
Comments
If you have a URL to an mp4 and you want frames, you first need to demux in into chunks (using a JS mp4 demuxing library) and then feed the chunk into a VideoDecoder. This example doesn't show you the demuxing portion, but it showcases a working WC example. It reads from a canvas and encodes the frames into chunks, then decodes the chunks into frames and draws them into another canvas: As far as MP4 demuxers go, I don't have a strong recommendation, but some people have used mp4box.js in demos. |
I get "(index):96 Encoding error: Unexpected frame format." in your demo. My chrome is 86.0.4240.75 is it a bug? |
It works for me (also 86.0.4240.75) on Linux. What platform are you using? |
Mac 10.15.6 |
We have been able to repro it a few times on our end, especially after clearing browsing data and reloading. Refreshing the page seems to fix the issue most of the time though. We already planned some work that would prevent this issue (automatic frame conversion to I420 for the encoder), but I have opened crbug.com/1137037 in the mean time to see if there is anything to be done. The issue is probably with the VideoTrackReader portion. For your use case, you should only need the VideoDecoder. |
Actually, you could try:
I have no idea what performance or guarantees you might get from this, and I don't know this area well at all. This just a way to get some frames out of a video with little code. VideoDecoder will offer you better reliability and controls. EDIT 23/02/2021: VideoTrackReader is now deprecated. Use the MediaStreamProcessor API instead (demo here) |
Looks like this is resolved. Please re-open if needed. |
Here is a code example for extracting the frames from an mp4: |
This is so cool! I notice at the bottom of the frame it's somehow extended vertically. Is it the same as the raw video? Looks like the raw video in https://tguilbert-google.github.io/webcodecs/mp4/bbb.mp4 does not have the extended bottom. |
Oh, this is because the video height should be 360 but you set it to be 368 lol |
Ah, thanks! That is a bug. I have opened crbug.com/1145244 |
Do I need to turn on |
Some frames are green ( tested in windows 10 surface pro 7 chrome 86.0.4240.198 ) visiting https://tguilbert-google.github.io/webcodecs/mp4/index.html ( same result both turning on/off chrome://flags/#enable-experimental-web-platform-features ) : |
Thanks for reporting. I think this may be a known issue fixed in Chrome 87. Can you try that version (beta channel)? |
Chrome 87 works! But the fix to crbug.com/1145244 seems to haven't been applied to 87 yet. |
Awesome, thanks for trying it!
Sadly that fix didn't make the branch cut for 87, but it is available Canary build now and will push out to Dev in a few days (any build >= 88.0.4316.0). |
Tested on mid 2014 mac, V10.13.5, chrome 87.0.4280.67 (Official Build) (x86_64)
( same result both turning on/off chrome://flags/#enable-experimental-web-platform-features ) |
Could you try on Chrome Canary and let us know if it repros there? |
Chrome Canary (89.0.4334.0) works properly on this old mac! But the stable version of 89 will be available after 99 days :( |
I'm sorry, but there's not much we can do about that... If it works on Dev/Beta (M88), that will be out sooner! |
Can you provide sample code for using the VideoDecoder after getting the frames from the mp4? Such as something similar to what is given with https://webcodecs-blogpost-demo.glitch.me/ but for the mp4 sample. @tguilbert-google |
Here's a demo that directly uses a VideoDecoder to read an MP4 file (it might take a while to load because the file is somewhat big): |
Actually, I'm not sure that answers your question @fnandoz21, as I had posted that link in an earlier comment. Was that what you were looking for? The key thing in that demo is that it demuxes the files itself. |
@tguilbert-google it doesn't really resolve it, I'm pretty much trying to do what's at https://webcodecs-blogpost-demo.glitch.me/ but with either an mp4 or frames derived from an mp4 instead of the rotating text. |
If you mean to have a video element, grab the frames from it, and display them in a canvas below something like this should work: This demo uses
The Otherwise:
Do you mean using the VideoEncoder after getting VideoFrames from the mp4? In the sense that you want to grab the frames from an mp4, encode them, decode them, display them, like in the https://webcodecs-blogpost-demo.glitch.me/ demo? |
Thanks for the reply! This code should be helpful. And to answer your question, yes, I want to grab the frames from an mp4, encode them, decode them, and display them. |
Also, is this what you mean by the video display code? Because this does not really work when I run it. I just get a blank screen. This also seems quite different from the webcam code. |
By display code, I mean this part of the mp4 demo:
The MediaStreamTrackProcessor webcam demo directly displays the MediaStreamTrack in the video element, and doesn't actually render anything. |
Ok that makes sense. Could you provide a way to take those frames and encode them to ImageBitmaps? I’m not sure if you showed that and the example from WebCodecs only shows how to do this with a drawing on a canvas, not with something that started as an MP4. I’m currently doing something based on the example from your website with the bbb.mp4 but it doesn’t appear that the bitmaps get populated with data. |
@tguilbert-google Hi the code snippet shared by you flawlessly worked for me in both Mac and Windows with Chrome Version 105.0.5195.127 (Official Build) (64-bit). Thank you for this solution. This looks promising and performant. I will test this more with large videos and let you know. Here is how modified the code to get it working, seems like value.createImageBitmap is outdated, I used createImageBitmap(value) by passing the frame value as a parameter of the same. Here is the implementation I did following your approach I will work more closely on this and update this thread. However, just letting you know, before I came across this, I have tried extracting media frames reliably using native javascript as well as using opencvjs, but both approaches were relatively slower and had issues which I posted on forums. Also lack of concrete documentation in this area is still a question mark for such implementations. OpenCV Implementation: https://forum.opencv.org/t/capture-all-frames-of-a-video-in-open-cv-js/10155 In both of these implementations there are bottlenecks such as large videos are not processed accurately for frames, however in a holistic view, the native javascript works accurately than the opencvjs implementation, but is slower than opencv js. |
If you need pixel data then using |
Here is my implementation using the webcodecs API that perfectly works |
You can drawImage() the returned VideoFrame object directly without going through createImageBitmap(). You can also use OffscreenCanvas instead of if you want. toBlob() will compress to png, but if that's what you want instead of the raw data that seems fine. |
@dalecurtis I will try removing the createImageBitmap and just rely on the canvas drawImage and update this thread again. Also, I might just end up using the offScreenCanvas instead of toBlob in the long run as I enhance this implementation further and delegate this entire process to a web worker for better performance and minimizing the risk of UI blocking. I will update the implementation further and keep you posted. This is a kind of POC I just completed in an hour being inspired from @tguilbert-google solution snippet above. I will enhance and shorten the code further and check in. And l also request you to review the implementation by cloning the project in your local, it would not take you more than 5 minutes. Thank you so much for your reply and recommendation. Means a lot🚀😃 |
Hello, I hovered over but does |
Yes you can use |
Thanks, is it possible to retrieve the VideoFrame's internal pixel array without having to duplicate it (read-only)? |
No, unfortunately JavaScript doesn't offer read-only arrays, so it wasn't possible to implement. The only way to get the data is via |
Thanks for the clarifications! |
I faced that obstacle and discovered a viable solution https://hypertexter.space/questions/having-trouble-capturing-a-photo-from-webcam-using-html5-and-getusermedia-in-google-chrome-upon-initial-page-load |
Given a url to a mp4 video, can we extract its frames using webcodecs? Is there any real code examples (e.g. jsfiddle) on how to do this?
The text was updated successfully, but these errors were encountered: