Skip to content

Instantly share code, notes, and snippets.

@alienresident
Last active April 20, 2024 05:02
Show Gist options
  • Save alienresident/8949291 to your computer and use it in GitHub Desktop.
Save alienresident/8949291 to your computer and use it in GitHub Desktop.
How to: Fix pseudo-streaming videos by moving Moov Atom
How to:

Fix pseudo-streaming videos by moving Moov Atom

Relies on some *nix CLI utilities: mediainfo; and qt-faststart (part of ffmpeg). I used homebrew to install them on OS X.

What is pseudo-streaming?

Pseudo streaming is simply a video that can start playing before it's fully dowmloaded. The videos are not streaming but rather progressively downloaded. What's important is that the file metadata (the Moov Atom) is at the start of the file rather than at the end. Usually this is an option set when encoding the file (called quick start or web start). If the files have not been encoded this way you can either re-encode or use a utility to move the Moov Atom. Re-encoding takes much longer than using a utility to move the Moov Atom so here's how to do it.

Steps

First check with mediainfo to see if video 'is streamable':

mediainfo "--Inform=General;IsStreamable: %IsStreamable%" Video.mp4 

Batch version to check with mediainfo if the videos are streamable (i.e the Moov Atoms are at the start of the files):

find . -name "*.m*" -type f | (while read FN ; do echo mediainfo "--Inform=General;IsStreamable: %IsStreamable%" "$FN"; done)   

Moving the Moov Atom using qt-faststart

If the output is IsStreamable: No then you can use qt-faststart (a utility in ffmpeg) to move the Moov Atom.

Example qt-faststart command:

qt-faststart video.mp4 video-NEW.mp4 

__Note:__This command creates a new video file.

Run qt-faststart with a batch command to convert a folder of videos:

for FILE in `find . -type f ` ; do NEWFILE=`echo "$FILE" | sed 's/.mov/_NEW.mov/g'` ; qt-faststart "$FILE" $NEWFILE ; done 

__Note:__This command creates new video files.

If you need to update the videos and keep the original filenames

A better approach would be to write the video files to a temp video and then replace it. However this works pretty well and I know how to do it this way.

First list the old files by inverse grepping (i.e. doesn't contain '_NEW')

ls | grep -v '_NEW'

If that lists the files you want to delete then delete the old files.

for FILE in `ls | grep -v '_NEW'` ; do rm $FILE ; done

Then rename files back to original by removing the '_NEW' at the end of the file name

for FILE in `find . -type f ` ; do NEWFILE=`echo "$FILE" | sed 's/_NEW.mov/.mov/g'` ; mv "$FILE" $NEWFILE ; done

Addendum: Dealing with spaces in the file names on *nix

Spaces can be problematic on *nix so I find it easier to remove them perform the programatic operation and put them back. There's probably a better way to deal with but this works for me.

Rename files with a control character '+' :

  • Double check control character isn't in the filename first
ls | grep '+'
  • Replace spaces with a control character '+' :
for FILE in *.m* ; do NEWFILE=`echo $FILE | sed 's/ /+/g'` ; mv "$FILE" $NEWFILE ; done
  • run qt-faststart
for FILE in `find . -type f ` ; do NEWFILE=`echo "$FILE" | sed 's/.mov/_NEW.mov/g'` ; qt-faststart "$FILE" $NEWFILE ; done 

First list the old files by inverse grepping (but this works for me.doesn't contain '_NEW')

ls | grep -v '_NEW'
  • If that lists the files you want to delete then delete the old files.
for FILE in `ls | grep -v '_NEW'` ; do rm $FILE ; done
  • Then rename files back to original by removing the '_NEW' at the end of the file name
for FILE in `find . -type f ` ; do NEWFILE=`echo "$FILE" | sed 's/_NEW.mov/.mov/g'` ; mv "$FILE" $NEWFILE ; done
  • Replace control character with spaces
for FILE in `find . -type f ` ; do NEWFILE=`echo "$FILE" | sed 's/+/ /g'` ; echo mv "$FILE" $NEWFILE ; done 
@DimitriHautot
Copy link

DimitriHautot commented Mar 23, 2020

Hello Mark,

Thanks for this nice set of recipes. I have a couple of remarks:

  1. Your second example, the batch version, is IMHO incomplete. It lacks some string pattern next to the echo command. I achieved something useful with this command: find . -name "*.m*" -type f | (while read FN ; do echo "$FN: $(mediainfo "--Inform=General;IsStreamable: %IsStreamable%" "$FN")"; done)

  2. Later in the page, you assume that the extension will be .mov, but it could also be .mp4 and .m4v. I'm definitely not a shell guy, but if you see an easy way to work with any extension, I'll happily share it with you!

Kind regards,

Dimitri

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment