9

I have a video file, and I need to encode it as H264/AVC and feed to client via HTTP. What i need is that i player at client side can play back the video as it is being encoded.

AFAIK, To enable player to play as the video is downloading, "moov atom" have to be placed at the begnning of the video file. However, encoders (ex: ffmpeg) always write "moov atom" at the end of file after it completes encoding.

Is there any way encoder can put "moov atom" at beginning of encode's output? Or play video without moov atom presence?

Thank in advances

LR

jAckOdE
  • 2,402
  • 8
  • 37
  • 67

4 Answers4

15

Yes, this is possible, but only in some container formats. It is NOT possible with a QuickTime/MP4 container. In these formats, the moov atom contains sample offsets (the locations of the samples in the mdat atom). These are not known until after the video has been encoded. With VOD (video on demand) you can take the finished file, and move the moov atom to the front, to make streaming work better. But there is no way to do this if you are encoding on the fly. To make that work, you'll need to use a stream-oriented transport format. Something like FLV or MPEG-TS would work. If you pass video into ffmpeg and tell it to produce H.264 video in an FLV container, you can then serve that data to a player as it's encoded, and it will work. Of course, if you want to serve it over HTTP, you'll probably have to write your own server (or module for an existing server). Nothing that I know of supports serving a file as it is written (an issue is that the file size is not known when the content-length header is sent). If you serve the video over RTMP or RTSP, however, you can make this work with existing software.

wombat57
  • 1,341
  • 1
  • 13
  • 26
  • Very thank! it's very helpful. I tried to encode a video file to H264 & AAC with mpegts as output option. the incomplete output file can be played by vlc while encoding. what i actually want is to play it on android, however android's player can not play incomplete output. I guess i have to implement my own player for android. – jAckOdE Jun 16 '11 at 11:06
  • I don't believe that Android guarantees support for MPEG-TS streams. (Although they may be adding support for Apple-style chunked http MPEG-TS streaming). What protocol where you using to get the video to the phone? Android supports RTSP over UDP (which VLC probably does as well) – wombat57 Jun 17 '11 at 18:10
  • video file is transfered to Android phone over HTTP and save in android phone as many small chunk, likes Apple's HTTP streaming. We can not use other protocol but HTTPs. I did check android site, and it's announced here saying that android support mpeg-ts from Android 3.0+: http://developer.android.com/guide/appendix/media-formats.html – jAckOdE Jun 20 '11 at 02:56
  • I usually encode to mkv for my own use, because players like vlc / mplayer / mpv can play partially-written mkv files. Seeking is slow in partial files, because the index isn't available, but it does work. – Peter Cordes Jul 07 '16 at 00:36
3

Perhaps it wasn't possible when @wombat57 wrote his answer, but it is possible now!

You want -movflags +frag_keyframe+empty_moov+faststart

As explained in this answer,

Normally, a MOV/MP4 file has all the metadata about all packets stored in one location (written at the end of the file, it can be moved to the start for better playback by adding faststart to the movflags, or using the qt-faststart tool). A fragmented file consists of a number of fragments, where packets and metadata about these packets are stored together. Writing a fragmented file has the advantage that the file is decodable even if the writing is interrupted (while a normal MOV/MP4 is undecodable if it is not properly finished), and it requires less memory when writing very long files (since writing normal MOV/MP4 files stores info about every single packet in memory until the file is closed). The downside is that it is less compatible with other applications.

Hut8
  • 6,080
  • 4
  • 42
  • 59
2

You can move the MOOV Atom to the beginning of a file by rewriting the file using a tool in ffmpeg called qt-faststart. You will need to compile it yourself from source code (but is quite easy at least in Linux / Mac OS). Just download the source of libavcodec, for example: http://libav.org/releases/libav-0.8.tar.xz

Untar it and go the tools directory, there is a file called qt-faststart.c, just build it with:

make qt-faststart

you can now reallocate MOOV Atom by calling it like this: qt-faststart input.mp4 output.mp4

manast
  • 96
  • 1
  • 3
1

I also tried this same thing earlier with ffmpeg, but could not succeed. But with vlc I was able to download, transcode and stream on Android simultaneously, though with rtsp. I did not try with http progressive method. I used mpeg4 video codec, mpega audio codec in vlc.

Muhammad Razib
  • 1,297
  • 9
  • 13
  • How did you get vlc to generate an rtsp stream that Android could handle? I keep getting "Unsupported format" / error -1010. I think maybe the problem is that there is no moov atom before the mdat atoms, but I'm far from sure! – Jon Shemitz Jun 04 '14 at 01:31