Open loretoparisi opened 4 years ago
@loretoparisi have you tried using https://github.com/alfg/ffprobe-wasm ? It probably needs a little polishing, but it should get the job done.
I'm currently working on a NodeJS project that needs ffprobe
.
Thank you @loretoparisi for the workaround.
You don't really need ffprobe to get the info. As long as we can get ffmpeg -i video.mp4
, be able to write the output log to a txt file, then parse to JSON, that would be nice. Unfortunately I haven't even been able to do that.
@goatandsheep I'm not sure that ffmpeg -i
can output all info as ffprobe
, may be yes.
I was looking to get the "file checksum" for Audible AAX files and while it doesn't show up with ffmpeg -i
, it does work with ffmpeg -v info -i *.aax
(or other verbosity values - quiet,panic,fatal,error,warning,info,verbose,debug,trace
). So if what you're looking for isn't in the default output, I'd suggest dialing it up.
Is there a way to get ffmpeg -i
output as a nice JSON? That would be nice.
@captn3m0 thanks I will have a look at -v info
. For JSON, in ffprobe
it's '-print_format', 'json'
, in ffmpeg
I never tried id.
-print_format
is a ffprobe only option :(
Any plan on support that?
It would be awesome to get format and stream metadata on browser. Something like that:
ffprobe -hide_banner -loglevel fatal -show_error -show_format -show_streams -print_format json video.mp4
ffprobe is so much faster than ffmpeg because it don't try to read the entire file.
Recently I had a use case where I needed to perform a duration check on media files on the browser before uploading to the server. I'll put my approach here while I built my POC as it is somewhat related.
Use case For context, my use case is as follows:
ffprobe-wasm is not the full ffprobe program
ffprobe-wasm
, but I quickly discovered that the program that is being executed is not actually ffprobe
, but ffprobe-wasm-wrapper.cpp
which is essentially an attempt to rewrite ffprobe
to be more emscripten friendly, but only contains a fraction of the utility that ffprobe
offers. The application as-is was insufficient for my use case as I needed to verify audio files as well.ffprobe-wasm-wrapper.cpp
at the time because it would essentially mean manually porting ffprobe
to wasm, something I lacked both the time and expertise to do. What I instead explored is to compile the entire ffprobe into wasm, something which I managed to successfully accomplish. My fork of the ffprobe-wasm repo can be found here: https://github.com/crazoter/ffprobe-wasm. The messy & uncleaned steps I took are as follows:docker-compose run ffprobe-wasm make
.emmake make fftools/ffprobe.o fftools/cmdutils.o
emcc --bind \
-O3 \
-L/opt/ffmpeg/lib \
-I/opt/ffmpeg/include/ \
-s EXTRA_EXPORTED_RUNTIME_METHODS="[FS, cwrap, ccall, getValue, setValue, writeAsciiToMemory]" \
-s INITIAL_MEMORY=268435456 \
-lavcodec -lavformat -lavfilter -lavdevice -lswresample -lswscale -lavutil -lm -lx264 \
-pthread \
-lworkerfs.js \
-o ffprobe.js \
ffprobe.o cmdutils.o
emmake make build
to build everything.my-dist
.ffmpeg-wasm
as the logs are async and there is no indicator to specify when the application has finished running.typeof SharedArrayBuffer !== "undefined"
to prevent the code from failing if you intended to use ffprobe without having to change your https headers.What I ended up using
ffmpeg-wasm
instead. ffmpeg-wasm
, but instead caused by how the emscripten file system is used. After all, we'd have to somehow bring the file into MEMFS before ffmpeg can even start processing it, and normally we just bring the whole file into MEMFS. What if we just bring in a slice of that?// Toy example
const maxSliceLength = Math.min(1024*1024*5, oFiles[nFileId].size);
const slicedData = oFiles[nFileId].slice(0, maxSliceLength);
(async () => {
ffmpeg.FS('writeFile', 'testfile', await fetchFile(slicedData));
await ffmpeg.run('-i', 'testfile', '-hide_banner');
ffmpeg.FS('unlink', 'testfile');
})();
maxSlicedLength / file.size
.Invalid data found when processing input
For these types of files, there are 2 options currently available:
MediaInfo
as it introduces complexity, so I decided to employ a much easier solution: audio tags which works well for mp4. Hopefully this write-up will benefit someone looking for a similar solution, or someone hoping to port ffprobe to wasm.
@crazoter What amazing post! Thank you so much. Got thrilled at each paragraph for in the end discover this amazing mediainfo.js, which apparently suits perfect for my needs. I am very happy now!
@crazoter Nice writeup! Thanks for checking out ffprobe-wasm
:
Still, for anyone interested in porting ffprobe to wasm, I think this is a step in the right direction and can be worth exploring. I am actually quite curious why the original authors of ffprobe-wasm didn't just compile the whole file.
I chose not to compile the FFprobe program, but instead to use libav directly to re-implement the functionality of FFprobe as an API via Wasm as an experiement, rather than the CLI through the browser. A different approach since you can interface with libavcodec and libavformat directly and provide minimal results. Though it's a bit more work to re-implement the full functionality of FFProbe, of course.
Hi everyone! I created an npm package a few months back. Repo is here: https://github.com/tfoxy/ffprobe-wasm . It comes with TS definitions.
I needed to use ffprobe in browser and Node.js so that I could read metadata without being affected by file size, so I tried to package the code at https://github.com/alfg/ffprobe-wasm so that it could be used as a library. The output tries to mimic the command
ffprobe -hide_banner -loglevel fatal -show_format -show_streams -show_chapters -show_private_data -print_format json
I don't know much about Emscripten or libavcodec/libavformat, so there are some properties that are missing. But hopefully this can be enough for some people.
EDIT: @crazoter thanks for providing those alternatives. In one project I only need the duration, so that solution of using HTMLMediaElement.duration
is great! Also didn't know about mediainfo.js
. Only thing that is not clear to me is if it needs to read the whole file to extract some of the metadata.
@tfoxy mediainfo.js
does not need to read the entire file, but imo acts strangely in regards to how much it needs to read, see: https://github.com/buzz/mediainfo.js/issues/108
I see that your ffprobe-wasm
project only supports FS, but not HTTP(s)? Are there any plans to support HTTP(s) too? (my interest is in retrieving chapter data of videos in nodejs, not the browser)
How is the progress of this issue?
Hi everyone! I created an npm package a few months back. Repo is here: https://github.com/tfoxy/ffprobe-wasm . It comes with TS definitions.
I needed to use ffprobe in browser and Node.js so that I could read metadata without being affected by file size, so I tried to package the code at https://github.com/alfg/ffprobe-wasm so that it could be used as a library. The output tries to mimic the command
ffprobe -hide_banner -loglevel fatal -show_format -show_streams -show_chapters -show_private_data -print_format json
I don't know much about Emscripten or libavcodec/libavformat, so there are some properties that are missing. But hopefully this can be enough for some people.
EDIT: @crazoter thanks for providing those alternatives. In one project I only need the duration, so that solution of using
HTMLMediaElement.duration
is great! Also didn't know aboutmediainfo.js
. Only thing that is not clear to me is if it needs to read the whole file to extract some of the metadata.
That's amazing! I was able to build and run the docker container and the application. But I'm struggling to import the generated module ffprobe-wasm.js
:
.
├── ffprobe-wasm.js
├── ffprobe-wasm.wasm
├── ffprobe-wasm.worker.js
within NodeJS, In fact if I try to load the module as usal
const Module = require('./ffprobe-wasm.js');
const versions = {
libavutil: Module.avutil_version(),
libavcodec: Module.avcodec_version(),
libavformat: Module.avformat_version(),
};
I get an TypeError: Module.avutil_version is not a function
error
So... any news? In my case, I need to get the exact timestamps of key frames (I-frames or whatever they're called). I was only able to find solution that requires ffprobe
ffprobe -select_streams v -show_packets -show_entries packet=pts_time,flags -of compact=p=0 -v quiet tua.mkv | grep flags=K > tua.frames.txt
There is a mention that ffmpeg can do something with key frames via command
ffmpeg -skip_frame nokey -i test.mp4 -vsync vfr -frame_pts true out-%02d.jpeg
but extracting, converting to JPEG, and then deleting thousands of files only because you need their file names seems silly to me.
*Insert "Fine, I'll do it myself" picture*
@loretoparisi Here, take a look: you can now call ffmpeg.ffprobe
command (just the way you would call ffmpeg.exec
one).
Is your feature request related to a problem? Please describe. Implement
ffprobe
wasm version.Describe the solution you'd like
ffprobe
is the necessary companion offfmpeg
, needed to analyze media file before processing .Describe alternatives you've considered In this simple case I'm using the command line
ffprobe
viaexecFile
to probe the fileor in this case to
seek
to position in the media file:Additional context Probe media files before processing; seek to media position;