Uploading multi-part videos as a single file? - join

I've got videos ( FLV ) set to split once they reach a certain filesize/length due to storage constraints, but I can't find a simple way to concatenate these files on the fly to upload them.
Currently it's looking like I'll have to concatenate the files using something like ffmpeg into an intermediary file and then uploading that, however that is rather intensive on resources and it would be much simpler if I could just tweak data in the stream I'm sending to youtube so the first file never "ends" and the next file can just be read in ( modified as it's read so it doesn't break ), and then youtube would "solidify" it when it processes the video.
So the question remains, is there any way to do this, or is the FLV file format ( wowza / flash video ) a bane to my plans?

No, there's no way to do that. You need to concatenate them first, and you need to specify the length of the entire video at the start of the upload (i.e. you can't just stream video bytes without knowing in advance the total upload size).

Related

How to build a simple video streaming server?

I am a newbie in video streaming and I just build a sample website which plays videos. Here i just give the video file location to the video tag in html5. I just noticed that in youtube the video tag contains the blob url and had a look into this. I found that the video data comes in segments and came across a term called pseudo streaming. Whereas it seems likes the website that i build downloads the whole file and plays the video. I am not trying to do any live streaming, just trying to stream local videos. I thought maybe the way video data is received in segments is done by a video streaming server. I came across RED5 open source streaming server, but most of the examples that is given is for live streaming which I am not experimenting on. Its been few days and I am not sure whether i am on the right track
The segmented approach you refer to is to support Adaptive Bit Rate streaming - ABR.
ABR allows the client device or player download the video in chunks, e.g 10 second chunks, and select the next chunk from the bit rate most appropriate to the current network conditions. See here for an example:
https://stackoverflow.com/a/42365034/334402
For your existing site, so long as your server supports range requests then you probably are not actually downloading the whole video. With Range Requests, the browser or player will request just part of the file at a time so it can start playback before the whole file is downloaded.
For MP4 files, it is worth noting that you need to have the header information, which is contained in a 'block' or 'atom' called MOOV atom, at the start of the file rather than the end - it is at the end for regular MP4 files. There are a number of tools which will allow you move it to the start - e.g.:
http://multimedia.cx/eggs/improving-qt-faststart/
You are definitely on the right track with your investigations - video hosting and streaming is a specialist area so it is generally easier to leverage existing streaming technologies and services rather than to build them your self. Some good places to look to get a feel for open source solutions:
https://gstreamer.freedesktop.org
http://www.videolan.org/vlc/streaming.html

http live streaming, a m3u8 file with loads of ts files, can I combine them into just one file?

I use the tools provided by apple to covert a .mp4 file into a m3u8 file and many .ts files. Then I uploaded those files to my server and use mpmovieplayercontroller to play the .m3u8 file and it worked.
my question is, since there are too many .ts files and this would be difficult to manage on our server, is it possible to combine them into a single file, but it still follows http live streaming? Thank you,
since there are too many .ts files and this would be difficult to
manage on our server, is it possible to combine them into a single
file, but it still follows http live streaming?
It is possible. Then you need to also alter the variant playlists so that that they use a byte-range request on the combined TS file. Once you know the byte offsets of each of the original segments into the combined file, this is not particularly hard to do: you need to add a number of #EXT-X-BYTERANGE tags to the playlist, which point the media player to the byte range to request from the media server.
Note that for #EXT-X-BYTERANGE to work you need a player that supports HLS version 4 or higher (which is anyway the near totality of iOS devices, and most Android devices).
You should use a class of software called "media servers" to do transmuxing, i.e. re-packaging on the fly. You'll be able to keep MP4 on your disk and have media server processing and caching it for all viewers.

Transcode/remux FLV and stream on the fly

I'm trying to teach myself a bit about video streaming and transcoding, with some Roku app development on the side. I have a number of video files (mostly in FLV format (H.264/AAC)) that I would like to stream to a client, which in this case is a Roku box (that accepts MP4 (H.264/AAC) and HTTP Live Streaming (HLS)). I'm wondering if it is possible to transcode/remux the FLV files and stream them to the client on the fly, perhaps over HLS?
I have tried using ffmpeg to remux the files and serve them immediately during the transcoding process, but they are unplayable until the write process is complete. I can get the Roku to play my completed MP4 files just fine via Apache/Rails.
But I'm wondering... is it possible to set up a server to transcode/remux a file and immediately have the output file (from ffmpeg/whatever tool I'm using) streamed to the client? If so, what tools are required to accomplish this? Is it possible to use a media file segmenter to chop up a file as it's being transcoded or remuxed?
I'm well aware that the transcoding process is CPU intensive, but I'm not so much worried about the practicality of transcoding and streaming on the fly since this is simply a personal education project (and I have an idle system that is capable if handling this).
Apologies if I'm way off base here, just trying to hack my way through this.
Thanks!
The trick to getting HLS served immediately that a TS segment has been completed is getting the playlist to dynamically update as the data arrives on disk.
What you are trying to do is essentially stream a Live event over HLS, which absolutely can be done, it just takes co-ordination between tools.
The opensource segmenter is able to do this, the trick is to have ffmpeg write out a single MPEG-TS stream (Unsegmented) and write this to a named pipe (Or equivalent for your OS), then have segmenter read from this named pipe and write the files to a directory within your shared webspace.
The segmenter repeatedly updates the M3U8 file on disk while processing so it can be used as a "Live" stream until the task is finished.
When ffmpeg closes its output the segmenter puts the end tag in the M3U8 and the file becomes "VOD".
The segmenter can be downloaded here

Join multiple audio files into one

I'm trying to allow selection of words (mp3 audio samples) and add to a sentence which upon pressing play plays them all in sequence and optionally save that one combined file.
MP3 is a stream format, meaning it doesn't have a bunch of metadata at the front or end of the file. While this has a lot of downsides, one of the upsides is that you can concatenate MP3 files together into a single file and it'll play.
This is pretty much what you're doing by concatenating into an NSMutableData, the downside of which is that you might run out of memory. Another option would be to build up the file on disk with NSFileHandle.
This doesn't work for most file formats (aac/m4a, aif, caf, etc.). MP3 is literally just a stream dumped to disk, with metadata in frame headers (or, in ID3, tucked between frames), so that's why it works.

How to implement the Adobe HTTP Streaming spec without using their Streaming server

As of Flash 10.1, they have added the ability to add bytes into the NetStream object via the appendBytes method (described here http://www.bytearray.org/?p=1689). The main reason for this addition is that Adobe is finally supporting HTTP streaming of video. This is great, but it seems that you need to use the Adobe Media Streaming Server (http://www.adobe.com/products/httpdynamicstreaming/) to create the correct video chunks from your existing video to allow for smooth streaming.
I have tried to do a hacked version of HTTP streaming in the past where I swap out the NetStream objects (similar to here http://video.leizhu.com/video.html), but there is always a momentary pause between the chunks. With the new appendBytes, I tried to do a quick mock up with the two sections of video from the preceding site, but even then, the skip still remains.
Does anyone know how the two consecutive .FLV files needs to be formated in order for the appendBytes method on the NetStream object to create a nice smooth video without a noticeable skip between the segments?
I was able to get this working using Adobe's File Packager Tool which Samuel described. I didn't use the NetStream object but I used the OSMF Sample Player which I assume uses this internally. Here's how to do with without using FMS:
Get Adobe's File Packager for Http Dynamic Streaming from http://www.adobe.com/products/httpdynamicstreaming/
Run the File Packager on an existing MP4 file containing H.264/AAC like this:
C:\Program Files\Adobe\Flash Media Server 4\tools\f4fpackager>
f4fpackager.exe --input-file="MyFile.mp4" --segment-duration=30
This will result in 30 second long F4F files, also F4X and a F4M file. The F4F files are your correctly segmented (and fragmented) MP4 files that should play.
If you want to test this using the OSMF Player also do the following:
Get Apache Server
Get Adobe's Http Origin Module for Apache from http://www.adobe.com/products/httpdynamicstreaming/
Install the module according to http://help.adobe.com/en_US/HTTPStreaming/1.0/Using/WS8d6ed60bd880807c48597a9e1265edd6cc0-8000.html
Put the F4F, F4X and F4M file into the vod directory under httpdocs
Get the “OSMF Sample Player for HTTP Dynamic Streaming” from http://www.osmf.org/downloads/OSFMPlayer_zeri2.zip
Put the Sample Player in the httpdocs directory
Load the html file from the Sample Player in a browser eg http://localhost/OSMFPlayer.html
Press the eject button and put in the URL of your F4M file, it should play
So to answer the original question Adobe's File Packager is the file splitter to use, you don't need to buy FMS to use it and it works for FLV and MP4/F4V files.
You don't need to use their server. Wowza supports Adobe's version of HTTP Streaming and you can implement it yourself by segmenting the videos properly and loading all the segments on a standard HTTP server.
Links to all the specs for Adobe's HTTP Streaming are here:
http://help.adobe.com/en_US/HTTPStreaming/1.0/Using/WS9463dbe8dbe45c4c-1ae425bf126054c4d3f-7fff.html
Trying to hack the client to do some custom style http streaming will be a lot more troublesome.
Note that HTTP Streaming does not support streaming several different videos but streams a single file that was broken off into separate segments.
File Packager
A command-line tool that translates on-demand media files into fragments and writes the fragments to F4F files. The File Packager is an offline tool. You can use the File Packager to encrypt files for use with Flash Access. For more information, see Packaging on-demand media.
The File Packager is available from adobe.com and is installed with Adobe® Flash® Media Server to the rootinstall/tools/f4fpackager folder.
Packager download link is on right here: Download File Packager for HTTP Dynamic Streaming
http://www.adobe.com/products/httpdynamicstreaming/
You could use F4Pack, it's a GUI around the commandline-tool from Adobe, that lets you process your flv/f4v file so they can be used for HTTP Dynamic Streaming.
The place in the OSMF code where this happens is the timer-fired state machine inside of the HTTPNetStream class implementation... might be an informative read. I think I even put some helpful comments in there when I wrote it.
As far as the general question:
If you read an entire FLV file into a ByteArray and pass it to appendBytes, it will play. If you break that FLV file in half, and pass the first half as a byte array and then the second half as a byte array, that will play as well.
If you want to be able to switch around between bitrates without a gap, you need to split up your FLV files at matching keyframe points... and remember that only the first call to appendBytes has the initial FLV file header ('F', 'L', 'V', flags, offset)... the rest just expect a continuation of the FLV byte sequence.
I recently found a similar project for node.js to achieve m3u8 transcoding (https://github.com/andrewschaaf/media-server) but have yet to hear of one besides Wowza doing it outside of Origin module for Apache. Since the payloads are nearly identical you're better off looking for a good mp4 segmenting solution (plenty out there) than looking for f4m segmenting. The problem is moov atoms especially on larger mp4 video are difficult to manage and put in their proper initial (near beginning of file) location. Even using optimal ffmpeg settings and 'qtfaststart' you end up with noticeably slower seeking, inefficient bandwidth usage (usually greedy), and a few minor headaches relating to scrubbing/time that you don't get with flv/f4v playback.
In my player I have or intend to switch between HTTP Dynamic Streaming (HDS) and MP4 based on load and realtime log parsing Apache using awk/cron instead of licensing Adobe's Access product for stream protection .. both have unique 'onmetadata' handlers.. but in the end I receive sequenced time/byte hashes virtually equivalent. Just MP4 is slower. So mod_origin is just a synchronizer / request router for Flash clients (over http). I'm still looking for ways to speed up mp4-container-based playback. One incredible solution I read this recently and was rather awestruck by it http://zehfernando.com/2011/flash-video-frame-time-woes/ where a video editor (guy) and flash developer came up with their own mp4 timecoding solution that literally added (via Adobe Premiere script) about 50 pixels to the bottom of every video frame with a visual 'binary' stamp like a frame barcode.. and those binary values translate into highly-accurate timecode values. So Flash could analyze the video frames as they were painted (realtime) and determine precisely where the player was and what bytes were needed from any kind of mp4 byte-segmenting-friendly webserver. The thing is (and perhaps I'm wrong here) Flash seems to arbitrarily choose when it gets to moov data, especially on large video files (.5-1.5gigs). Even if you make sure to run your mp4 through MP4Box (i.e. MP4Box -frag 10000 -inter 0 movie.mp4) I guess this has been a problem OSMF and HDS have worked on quite well
now, though it is annoying that you need Apache and a proprietary closed-source module to use it imo. Its probably just a matter of time before open source implementations arrive as HDS is only 1-2 years old, and it just needs a little reverse engineering like that Andrew Chaaf guy with node.js + mpegts streaming (live or not).
In the end I may just end up using OSMF exclusively beneath my UI as it seems to have similar virtues to HDS if not more so i.e. Strobe if you need sick extensible HDS or MP4 open player platform to hack from to realize your own custom player.
Adobe's F4F format is based on MP4 files, are you able to use F4V or MP4 instead of FLV files?
There are plenty of MP4 file splitters around but you would need to make sure the timestamps in the files are continuous, maybe the pause happens when it sees a zero timestamp within the audio or video stream inside the file.

Resources