Does anyone know how I can return what frame the video would be on at a certain point ?
so for example the video is playing and I press a js button ive made and it returns the current frame the video is on and prints it on screen .
There's no way to know the exact frame of the video from the html5 video element, but if you know the frame rate (e.g. 30 fps) up front you could do the calculation.
var frame = Math.floor(myPlayer.currentTime() * frameRate);
Related
With the help of waveformjs.org I am able to draw waveform for a mp3 file. I can also use
wav2json to get json data for audio file hosted on my own server and I don't have to depend on soundcloud for that. So far so good. Now, the next challenges for me are
To fill the color in waveform as the audio playing progresses.
On clicking anywhere on waveform audio should start playing from that point.
Has anyone done similar? I tried to look into soundcloud js SDK but no success. Any pointers in this directions will be appreciated, thanks.
As to changing the color my earlier answer here may help:
Soundcloud modify the waveform color
As to moving the position when you click on the waveform you can do something like this:
Assuming you have a x position already from the click event adjusted relative to the canvas.
/// get a representation of x relative to what the waveform represents:
var pos = (x - waveFormX) / waveformWidth;
/// To convert this to time, simply multiply this factor with duration which
/// is in seconds:
audio.currentTime = audio.duration * pos;
Hope this helps!
Update
The requestAnimationFrame is optimized not only for performance but also power consumption as more and more users are on mobile devices. For this reason the browsers may or may not pause or reduce frame rate of rAF when in a different tab or when browser tab is invisible. This can cause a position based approach to render the waveform delayed or not at all when tab is switched.
I would recommend to always use a time based approach so neither FPS or other behavior will interrupt the drawing of the waveform.
You can force the waveform to be updated at the actual current time as luckily we can attach this to the currentTime property of the audio element.
In the rAF loop simply update the position like this using a "reversed" formula of the above:
pos = audio.currentTime / audio.duration * waveformWidth + waveformX
When the tab becomes visible again this approach will make sure the waveform continues based on the actual time position of the audio.
OK, I have seen a lot of questions and answers on how to code pause/resume buttons, but none of them fit my specific need. First let me explain what I have:
I have made a tutorial video for my job. It consists of screens shots and sounds. I have a forward button that skips to the next section (usually the start of the next audio file) and a back button that goes to the previous section. However I need a pause button.
Now let me explain how I have built it:
I have made the movie at 1fps. I have a layer for Audio, a layer for the screen shots, a layer for each button, and various other layers for highlighting things in the screen shots. On the Audio layer I placed my audio file on the stage and then dragged out the number of frames until the entire audio file could play uninterrupted. So if the audio was 10 seconds long, it lives across 10 frames. I can then put my screenshot on its own layer and do the same so that the image displays the same length of time as the audio. When the frame ends, it automatically skips to the next frame and continues on until the end. Since the audio is on the stage, the viewer doesn't need to do anything to get the audio to play.
After viewing many tutorials, it seems like most people use code to get the audio to play rather than putting it on the stage. I am not this skilled.
So my question is, with my current set up, how can I make a toggle button that basically says "If audio is playing, stop the whole show when clicked- if audio is not playing, resume show from last position when clicked"?
Thank you so much if you can help! Also, this is my first time asking a technical question like this, please let me know if you need any other specific details.
First make sure all audios on your timeline are set to "Stream". To
do this click on the frame where your audio lies, find the sound
panel, change it from Event to Stream. this will ensure that when
the timeline is stopped the audio stops and resumes when the
timeline is played.
As for the buttons simply make one that calls stop() on the timeline and one that calls play(). This will stop the timeline wherever it is and resume it on play.
var myTimeline:MovieClip;//link to the movieclip where your timeline animation lies
var btnPause:SimpleButton;//link to your pause button
btnPause.addEventListener(MouseEvent.CLICK,function(event:MouseEvent):void{
myTimeline.stop();
});
var btnResume:SimpleButton;//link to your resume button
btnResume.addEventListener(MouseEvent.CLICK,function(event:MouseEvent):void{
myTimeline.play();
});
When I am streaming a video (using RTMP) in my flash player (AS3) - the frames I see are colored [b]a bit [/b] differently than the frames in the original video !
I would like to somehow save the frames I am showing in my player to an image sequence,
so that I can examine it and understand the difference between each frame I was showing from the stream to the original frame in the original video.
How can this be achieved ? (the video is 5 minutes long, and has 25 frames-per-second).
First you should set the following flags on the fms script, which allows you to access the streaming video or audio.
application.onConnect = function(client,....)
{
...
client.audioSampleAccess = "/";
client.videoSampleAccess = "/";
}
Secondly on the client side, you may use the BitMapData.draw method to capture the video from the VideoDisplayObject
var snapshot:BitmapData = new BitmapData(video.width, video.height);
snapshot.draw(videoDisplay);
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.
I have this custom video player I'm making. I need some way to react when the externally played flv file reaches a certain point in the movie without embedding some extra data on the flv file. I am looking for this because I want to react at the 90%-99% point of the movie because I didn't like the behavior I'm getting when I react when the stream completes playing (I want a bit earlier). How do I achieve this?
I'm surprised Adobe didn't document what is the object structure passed on things like onMetaData and onCuePoint...
You can achieve this with a little math. Position of play head divided by duration multiply by 100.
If value is greater than 90 fire your event.
((p / d) * 100)
You can do this by programmatically setting a cue point based on the length the movie clip, then creating an event listener for it.
var endpoint:Number = flvPlayer.metadata.duration*.95; //95% of the video length
flvPlayer.addASCuePoint(endpoint, "endpoint");
flvPlayer.addEventListener(MetadataEvent.CUE_POINT, registerCuePoints);
function registerCuePoints(myEvent:MetadataEvent) {
if(myEvent.info.name == "endpoint") {
// you've reached your cue point, not something embedded in the video.
}
}