AS NetStream start buffering at determinate second - actionscript-3

I'm having some problems to start playing an external video file at determinate time.
I want to load an external mp4 or flv file and the player must start to play it at a determinate time ( ex at 100 second ). The same way of selecting a video part on the seek bar. But, using NetStream.seek, it will buffer all the video from 0 to selected second, then the video starts. But it have to start buffering to the given second time.
How can i do it ?

It should be supported by the server side, so syntax depends on the server, e.g. stream.play("file.flv?start=100000");
Btw there's a general advice that you should seek to unbuffered position only to a keyframe to avoid display of changes on a monochrome background instead of a keyframe. Information about keyframes' times and filepositions can be found it the video file metadata object

Related

Media Source - is it possible to have buffer that don't start with a key frame?

Using the media source extension, is it possible to do buffering in a way that buffers don't start with a key frame, but with a normal frame?
For instance, is it possible to buffer the video frame by frame? (Not saying that would be very smart to do!)
It is possible but obviously you won't be able to see video until you feed it with a key frame.
Having said that, there is currently a limitation in Chrome causing failure to play video if fragments don't start with a key frame.
see here:
https://bugs.chromium.org/p/chromium/issues/detail?id=229412

Flash Video Loading Issue

Please click on the below link
http://hpecp.vmokshagroup.com/videobook/html/homepage.html
When we click on "What is VideoBook" link we got some blank screen before starting the swf file due to video fetching from the server. We have to avoid blank screen.
We are facing a problem of fetching the video clips from the hosting server. I added two video clips in Flash (.swf)... one is from the beginning, another one is at the ending and in between some text animations.
While we are playing/calling .swf file in browser from hosting server, initially getting blank screen. It takes some time to fetching the video clip from server due to size. Starting of first video clip duration is about 3-6 seconds. While video is being loaded.. text animation is starting without playing first video clip. Same problem we are facing in second video at the ending.
Is there any option to incorporate video clips internally in Flash (.swf file) rather than calling from external server or external file path?
Any help would be appreciated.
This happens because of the JavaScript that you use - it actually makes the swf files (in)visible depending on the situation. What this does is that it actually loads the .swf files each time. You can check that in the Network tab of your debugger (I'm using Chrome).
So it first loads Video-01d.swf, or Video-02.swf. They take time to load, and just when the main file is loaded, it starts to load the video file (video1.flv).
All that causes delay, and it's pretty normal as you have all that things in separate files. If you want to, you can merge them into one - just import the flv inside your .swf file and it will work out well..
Of course, you will need to change all your logic for the flash files that you are playing. You will also need to change the JavaScript to call Flash functions in order to tell it to go to another "scene".
I will advise you to add a simple gif loader image (like this), put it as a background-image of the div, and put some color into that div. What the user will see is that the movie disappears, there is a black background with a loading symbol inside, and then the new video begins. It's a normal thing to see online - preloaders :) Good luck!

How can I emulate live video streaming

I'm interested in uploading a series of files to my web server and directing viewers to page which will autoplay the videos from a specific point dependent on the current time. My intention is to create the illusion of a live stream or actual TV channel, where they are unable to control the playback, but will return to the same point if they refresh the page.
I'm having difficulty finding answers, since it's descriptively so close to an actual webcast.
Here's my thought process on a solution.
Use the JavaScript Date Object API to capture the current time
Include your video with preload set to true, and controls false
Then use onLoad() and setup your video in JS
$(video).get(0).currentTime = XX; //You need an algorithm based on the time & length of video
$(video).get(0).play();

How does Youtube's HTML5 video player control buffering?

I was watching a youtube video and I decided to investigate some parts of its video player. I noticed that unlike most HTML5 video I have seen, Youtube's video player does not do a normal video source and instead utilizes a blob url as the source.
Previously I have tested HTML5 videos and I found that the server starts streaming the whole video from the start and buffers in the background the complete rest of the video. This means that if your video is 300 megs, all 300 megs will be downloaded. If you seek to the middle, it will start downloading from the seek position all the way to the end.
Youtube does not work this way (at least in chrome). Instead it manages to control buffering so it only buffers a certain amount while paused. It also seems to only buffer the relevant pieces, so if you skip around it will make sure not to buffer pieces that are unlikely to be watched.
In my attempts to investigate how this worked, I noticed the video src tag has a value of blob:http%3A//www.youtube.com/ee625eee-2802-49b2-a13f-eb374d551d54, which pointed me to blobs, which then led me to typed arrays. Using those two resources I am able to load a mp4 video into a blob and display it in a HTML5 video tag.
However, what I am now stuck on is how Youtube deals with the pieces. Looking at the network traffic it appears to sends requests to http://r6---sn-p5q7ynee.c.youtube.com/videoplayback which returns binary video data back in chunks of 1.1mb. It also seems worth noting that most normal requests due to HTML5 video requests seem to receive a 206 response code back while it streams, yet youtube's playvideo calls get a 200 back.
I tried to attempt to only load a range of bytes (via setting the Range http header) which unfortunately failed (I'm assuming because there was no meta-data for the video coming with the video).
At this point I'm stuck on figuring out how Youtube accomplishes this. I came up with several ideas though none of which I am completely sold on:
1) Youtube is sending down self contained video and audio chunks with each /videoplayback call. This seems like a pretty heavy burden on the upload side and it seems like it would be difficult to stitch these together to make it appear like it's one seemless video. Also, the video tag seems to think it's one full video, judging from calling $('video').duration and $('video').currentTime, which leads me to believe that the video tag thinks it's a single video file. Finally, the vidoe src tag never changes which makes me believe it is working with a singular blob and not switching out blobs.
2) Youtube constructs an empty blob pre-sized to the full video array and updates the blob with pieces as it downloads it. It would then make sure the user has not gotten too close to the last downloaded piece (to prevent the user from entering an undownloaded section of the blob). The problem that I see with this that I don't see any way to dynamically update a blob through javascript (although maybe I'm just having trouble googling for it)
3) Youtube downloads the meta data and then starts constructing the blob in order by appending the video pieces as it downloads them. The problem I see with this method is I don't understand how it would handle seeks in post-buffered territory.
Maybe I"m just missing an obvious answer that's right in front of me. Anyone have any ideas?
edit: I just thought of a fourth option. Another idea is they might use the file API to write the binary chunks to a file and use that file to stream off of. The file API seems to have the ability to seek to specific positions, therefore allowing you to fill a video with empty bytes and fill them in as they are received. This would definitely accommodate video seeking as well.
Okay, so few things you need to know is that YouTube is based on this great open source Project. It behaves different for every browser and if your browser supports more intensive decoding like WEBM it will use that to save Google's bandwidth. Also if you look at this Demo
Then you will find a section which downloads the entire video into a thing called "offline storage". I know chrome has it and some other browsers not every in some cases they do have to use the entire video source instead of a blob. So that blob is streaming depending on the user interaction with the video. Yes the video is just 1 file and they have metadata for that video like a little database that tells the time of the video and the points at which chunks can be divided in.
You can find out more by reading the Project's documentation. I really recommend you have a look at the demo.
When you look at the AppData of GoogleChrome, while playing a youtube video, you will see that it buffers in segmented files. The videos uploaded to youtube are segmented, which is why you can't perfectly pinpoint a timeframe in the first click on the bar if that timeframe is outside of the current segment.
The amount of segments depends on the length of the video, and the time from which you start and stop playing back the video.
When you are linked to a timeframe of a video, it will simply skip the buffering of the segments that come before that timeframe.
Unfortunately I don't know much about the coding for video playback, but I hope this points you in the right direction.
there is a canvas element in the page ,Maybe This Will Help
http://html5doctor.com/video-canvas-magic/
we knew the video is been segmented,the question is how to stitch them together.i think the real video element doesn't do the play work,it support the datasource,and draw the seagments each frame to the canvas element。
var v = document.getElementById('v');
var canvas = document.getElementById('c');
v.addEventListener('play', function(){
if(v.paused || v.ended) return false;
c.drawImage(v,0,0,w,h);
setTimeout(draw,20,v,c,w,h);
},false);
Youtube is using this feature only in browsers that support Media Source Extensions so it is up to the browser decide about all the rest because of this feature.

Netstream and step() or seek()?

I'm on an AS3 project, playing a video (H264). I want, for some special reasons, to go to a certain position.
a) I try it with NetStream.seek(). There it only goes to keyframes. In my current setting, this means, i can find a position every 1 second. (for a better resolution, i'd have to encode the movie with as many keyframes as possible, aka every frame a keyframe)
this is definetly not my favourite way, because I don't want to reencode all the vids.
b) I try it with NetStream.step(). This should give me the opportunity to step slowly from frame to frame. But in the documentation it says:
This method is available only when data is streaming from Flash Media Server 3.5.3 or higher and when NetStream.inBufferSeek is true.
http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/net/NetStream.html#step()
Does this mean, it is not possible with Air for Desktop? When I try it, nothing works.
Any suggestions, how to solve this problem?
Greetings & Thank you!
Nicolas
Flash video can only be advanced by seconds unless you have Flash Media Server hosting your video. Technically, that means that you can have it working as intended in Air, however, the video would have to be streaming (silly adobe...).
You have two options:
1) Import the footage as a movieclip. The Flash IDE has a wizard for this, and if you're developing exclusively in non-FlashIDE environment, you can convert and export as an external asset such as an SWF or SWC. This would then be embedded or runtime loaded into your app giving you access to the per-frame steppable methods of MovieClip. This, however, does come with some audio syncing issues (iirc). Also, scrubbing backwards is not an MC's forté.
2) Write your own video object that loads an image sequence and displays each frame in order. You'd have to setup your own audio syncing abilities, but it might be the most direct solution apart from FLVComponent or NetStream.
I've noticed that flash player 9 scrubs nice and smooth but in players 10+ I get this no scrub problem.
My fix, was to limit frequency the calls to the seek function to <= 200ms. This fixed scrubbing but is much less smooth as player 9. Perhaps because of the "Flash video can only be advanced by seconds" limitation? I used a timer to tigger the function that calls seek() for the video.
private var scrubInterval:Timer = new Timer(200);
private function videoScrubberTouch():void {
_ns.pause();
var bounds:Rectangle = new Rectangle(0,0,340,0);
scrubInterval.addEventListener(TimerEvent.TIMER, scrubTimeline);
scrubInterval.start();
videoThumb.startDrag(false, bounds);
}
private function scrubTimeline(e:TimerEvent):void {
var amt:Number = Math.floor((videoThumb.x / 340) * duration);
trace("SCRUB duration: "+duration+" videoThumb.x: "+videoThumb.x+" amt "+amt);
_ns.seek(amt);
}
Please check this Demo link (or get the SWF file to test outside of browser via desktop Flash Player).
Note: Demo requires FLV with H.264 video codec and AAC or MP3 audio codec.
The source code for that is here: Github link
In the above demo there is (bytes-based) seeking and frame by frame stepping. The functions you want to study mainly are:
Append_SEEK ( position amount ) - This will got to the specified position in bytes and search for the nearest available keyframe.
get_frame_TAG - This will extract a tag holding one frame of data. Audio can be in frames too but lets assume you have video-only. That function is your opportunity to adjust timestamps. When it's run it will also append the tag (so each "get_frame_TAG" is also a "frame step").
For example : You have a 25fps video, you want the third-frame at 4 seconds into playback...
1000 milisecs / 25 fps = 40 units for each timestamp. So 4000 ms == 4 secs + add the 40 x 3rd frame == an expected timestamp of 4120.
So getting that frame means... First find a keyframe. Then step through each frame checking the timestamps that represent a frame you want. If it isnt then change it to the same as most recent keyframe timestamp (this forces Flash to fast-forward through the frames to keep things in sync as it assumes the frame [with smaller than expected timestamp] should have been played by that time). You can "hide" the video object during this process if you don't like the look of fast-forwarding.