4
$\begingroup$

I know how to import videos into Mathematica using the FFmpeg package (Mathematica's built-in import for AVIs rarely ever works for me or anyone, since Mathematica is usually missing the right codecs), and I can then play the videos using ListAnimate. The problem is, when I do that, video compression is lost, and the notebooks become gigantic: For the particular example I am currently working on, I have a .wmf video that's roughly 35MB, but when I import that into Mathematica I end up with a notebook file that's about 775MB. Is there a way to import and animate compressed video formats in Mathematica?

Mind you, the main application I have in mind right now is importing and displaying videos in, say, a Mathematica slideshow, the way I can do that in PowerPoint. I'm not interested in saving compressed video externally, unless Mathematica would be able to load and display such videos directly.

Finally, ideally I would like to display just the running videos, with no control elements whatsoever. I haven't figured out how to do this, however. I can display a hide button with the AppearanceElements -> "HideControlsButton" option, but if I hide the controls then the video stops running. AppearanceElements->None on the other hand seems to have no effect.

$\endgroup$
  • $\begingroup$ "I'm not interested in saving compressed video externally, unless Mathematica would be able to load and display such videos directly." - but you've already said that you can load the video with ffmpeg and display with ListAnimate. Why not do that? Why do you need to save the movie data inside the notebook? $\endgroup$ – Simon Woods Feb 25 '17 at 22:47
  • $\begingroup$ @Simon Woods It looks like once you have read in the video frames they will be stored in the notebook. Even if that was not the case, reading in the video frames on demand is far, far too slow to be practical. The issue is that when Mathematica loads the video frames, they get decompressed, which is the reason for the substantial increase in size. $\endgroup$ – Pirx Feb 25 '17 at 22:50
  • $\begingroup$ Yes, this seems possible. For your first problem, you could read the file as binary data (not import it and uncompress it). You can include this data directly inside your dynamic cell. When you want to watch the video, you can convert the binary data to images as you would do with Import and display the animation. For your second problem, the most painless way is probably to just write the few lines of code that display a list of images with a fixed delay. You don't really need ListAnimate for this. $\endgroup$ – halirutan Feb 26 '17 at 5:19
  • $\begingroup$ With this approach, you have your videos compressed in the notebook and the notebook is small on disk. When you make your presentation, then of course the uncompressed versions are required and your RAM will contain the memory for the images. $\endgroup$ – halirutan Feb 26 '17 at 5:21
  • $\begingroup$ Hmm, yes, I see what you are suggesting. However, then the problem arises as to how I can process the object I have read into Mathematica as binary data. My guess is that this would require either writing a video decoder in Mathematica myself (out of the question, I know nothing about video decoding), or somehow integrating the available ffmpeg source code via some clever MathLink programming, which I am also not competent to do. $\endgroup$ – Pirx Feb 26 '17 at 16:04
2
$\begingroup$

If you run on Windows you could use MathMF for this. In the example below the video frames are loaded on demand and displayed using Monitor.

Needs["MathMF`"]

playmovie[filename_] := Catch @ Module[{t0, image},
   Check[MFInitSourceReader[filename], Throw[$Failed]];
   t0 = AbsoluteTime[];
   While[image =!= EndOfFile,
     Pause[Max[MFSourceTime[] + t0 - AbsoluteTime[], 0]];
     image = MFGrabFrame["ByteImage"]
     ] ~Monitor~ image]

playmovie["20130703_141431.mp4"] 
(* movie appears here *)

Screenshot:

enter image description here

$\endgroup$
  • $\begingroup$ Hah, this does what I want. Thanks! $\endgroup$ – Pirx Feb 27 '17 at 12:16
1
$\begingroup$

I quickly looked through the FFmpeg package. It seems it only works on files. However, since it basically uses a system call to ffmpeg to retrieve the frames, I'm sure this can be adapted so that you can feed the binary data instead of a file to this call.

That being said, I'm going to show how you can include the binary data inside a DynamicModule to make it self-contained. As example, I'm going to use a png image:

inlinedBinaryImage[path_] := Module[{data},
  data = Import[path, {"Text", "String"}];
  With[{d = data},
   DynamicModule[{img = "Please Click to decompress image"},
    Panel@ClickPane[
      Dynamic[img],
      Function[Null,
       img = ImportString[d, "PNG"]]
      ]
    ]
   ]
  ]

With this function, you can load and store the compressed png file inside and when you click on the pane, it is decompressed with ImportString. In your real application, you need to replace the ImportString call with whatever function decodes your video data.

inlinedBinaryImage["~/tmp/test.png"]

Mathematica graphics

and when you click, the image is reconstructed

Mathematica graphics

$\endgroup$
  • $\begingroup$ That's an interesting approach, too. This way I could "embed" the compressed video in the notebook file so have everything I need in a self-contained file. $\endgroup$ – Pirx Feb 27 '17 at 12:19

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.