Importing videos in Mathematica
64-bit Windows only
Note for Mathematica 11.3: There is a potential conflict between
MathMF
and the built-inMediaTools
package. See here for details and here for an example of how to useMediaTools
in place ofMathMF
.
Note for Mathematica version 10: The Wolfram Library has been updated in version 10 and you will need to recompile the MathMF DLL. This is most easily accomplished by evaluating
"MathMF"//FindLibrary//DeleteFile
prior to loading the package.
Link to package on GitHub
I have written a package called MathMF which uses a LibraryLink
DLL to do frame-by-frame video import and export with Windows Media Foundation. It should be able to read a reasonable variety of movie files, including AVI, WMV and MP4. Exporting is currently limited to WMV and MP4 formats (AVI encoding is not natively supported by Media Foundation)
Here is the sort of code you can write with it. The code first opens a video file for reading, and creates a new video file for writing to. It then runs a loop in which each frame is sequentially read from the input stream, processed in Mathematica and then written to the output stream. So Mathematica is effectively being used as a video filter.
{duration, framerate, width, height} =
MFInitSourceReader["C:\\Users\\Simon\\Desktop\\test1.wmv"];
MFInitSinkWriter["C:\\Users\\Simon\\Desktop\\filtered.wmv",
width, height, "FrameRate" -> framerate]
While[
(image = MFGrabFrame["RealImage"]) =!= EndOfFile,
MFSendFrame @ GradientFilter[image, 2]
] ~Monitor~ image
MFFinaliseSink[]
The package can be downloaded from the GitHub link at the top of this post, it is too large to include in full here.
The package includes the library source code, and on first use will attempt to compile the library locally. I believe the compilation should work if you have Visual Studio 2010 or later installed, and probably won't work if you use a different compiler. There is a pre-built DLL available if the compilation fails (see the readme on GitHub for more details)
I hope some people find this useful, it has been hovering in my mind as something to try to do for quite some time, hindered mainly by my total lack of experience with C++ and COM programming.
(Thanks to K.H. from Wolfram):
Even on Windows, if QuickTime is installed, Mathematica uses the native QuickTime install (excluding added, third-party codecs) to import AVI files, and the supported codecs are listed in:
Internal`$VideoEncodings
(Without an installation of QuickTime, only uncompressed AVI files are supported by Mathematica.) For the file http://people.sc.fsu.edu/~jburkardt/data/avi/ccvt_box.avi, QuickTime on Windows can not open it, so Mathematica has problem importing it.
If you only need to access the video frame by frame you can use ffmpeg to decode the video.
Reposting a previous answer:
If you only want to read it linearly you can tell ffmpeg to dump the video to stdout and then read widthheightbytes-per-pixel bytes at a time to get the video frame-by-frame:
openVideo[fname_, w_, h_] :=
Module[{video},
video["stream"] =
OpenRead[
"!ffmpeg -i " ~~ fname ~~ " -loglevel quiet -f rawvideo -pix_fmt rgb24 -",
BinaryFormat -> True];
video["SkipFrame", n_Integer: 1] := Skip[video["stream"], Byte, n*3*w*h];
video["NextFrame"] := Partition[Partition[
BinaryReadList[video["stream"], "Byte", 3*w*h]
, 3], w];
video["NextFrame", n_Integer] := Table[video["NextFrame"], {n}];
video["NextImage"] := Image[video["NextFrame"], "Byte"];
video["NextImage", n_Integer] := Table[video["NextImage"], {n}];
video]
Here's an example:
(* Create a test movie *)
file = $TemporaryPrefix <> "testvid.avi";
Export[file,Table[Rasterize[i, ImageSize -> {352, 200}], {i, 1, 50}]];
video = openVideo[file,352,200]
video["NextImage",2]
video["SkipFrame",10]
video["NextImage"]
For some reason Mathematica seems to read through the entire video when doing Close[video["stream"]]
and it might be worth to kill -15
the ffmpeg process manually to speed it up for large files.
For a 720x404 h264 mp4 video on a modest laptop it takes 13s to skip 200 frames and 0.07s to read a frame. The skipping could possibly be sped up by starting a new ffmpeg process that begins at desired frame. I would compare speeds to Import
but Mathematica can't read it (for the test video Import takes .2s for first frame compared to .02s ). So as a bonus with this way you can work with many many more video formats :)