SWF file seek information - actionscript-3

Is it possible to get and set seek position of a swf file (either in ActionScript 2/3 or ActiveX API of Flash Player) ?
I tried to use frame number at first (to determine which part of the movie is being played) however sometimes whole animation has 2 frames and it does not help.
Any ideas?
Thanks.

if your loaded SWF contains all animation on the stage timeline ( i mean the top level ) then the progress you are seeking is:
var progress:Number = swf.currentFrame / swf.totalFrames;
if you want to set seek:
swf.gotoAndPlay ( progress * swf.totalFrames )
Also it can be that the all animation is not on the top level, but in the movieClip, which address you know, i mean stage.getChildByName ( 'something ).getChildeByName ('something )...
but if you have an swf where are multiple movieclips, and they are playing independantly, then nothing i can help....

Not without coding something in to the SWF as far as I know. Because animations in Flash can be in embedded MovieClips, or entirely scripted in a single frame, there is no easy way to detect the total playing time or how far an animation has progressed. Any get/seek functionality, or even a progress broadcast, would have to be scripted in the SWF and accessed through ExternalInterface.

Please be more specific about your problem. If your swf file is only 2 frames, then what is it that you are trying to seek through? Does your swf load a video, for example, and this is what you are trying to seek through? (In which case you can get properties of a video object's playback position and state).
Without more information, it's hard to provide a clear answer.

Related

Avatar Layering and Animating in Flash

So for my latest Flash project, I'm designing a game. The dimetric character can move in 8 directions. I've been given the spritesheets for the hats, hair styles, etc., that the player can wear.
The spritesheets contain the images for each direction, AND they contain four frames of animation (four per direction) for when the player is walking. This is basically the layout of the Spritesheet (and all of the files and "frames" are the same size, which makes things easier):
[IDLE] [WALKING]
[S][SE][E][N][NW][W][S1][S2][S3][S4][SE1][SE2]...
My goal is to embed all of the items in a single file other than the main one. But I need to implement walking animation.
One thought I had is to set the main SWF's framerate to 7 FPS, then use an Event.ENTER_FRAME handler to alternate between the walking ones. Programmatically animating.
Another thought is to create SWFs for each item of clothing, then use motion tweening to move the spritesheet symbol over the stage.
What I'd really like it so avoid using Adobe Animate entirely. Even if there's an approach that requires the use of Flex, I'd take it if it meant saying goodbye to graphically-designing.
using flash builder (flex) does not mean that good bye graphic! there is a relationship between Adobe Flash and any As3 Ide like FlashBuilder or FlashDevelop.
exporting movieclips and everything in library with .swc format, and then importing it by the IDE, read this
My goal is to embed all of the items in a single file other than the
main one. But I need to implement walking animation.
One thought I had is to set the main SWF's framerate to 7 FPS, then
use an Event.ENTER_FRAME handler to alternate between the walking
ones. Programmatically animating.
i dont undrestand! why 7 fps and also why Event.ENTER_FRAME
there might be a character movieclip, whit above frames in its time line, well! to playing any animation (for particular direction) you have to call mc.gotoAndPlay("walk_S"); then it will be played automatically, if you need lower frame rate, only select each frame by mouse pointer and then press [F5] in time line to insert a blank frame gape between keyframes.
as i said before, you must use a callback script at the end frame of the each loop animation like walk_s walk_ne ...
also idle animations must be called like it: mc.gotoAndStop("idle_s");

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.

How to react when an externally played FLV reaches Nth frame or percentage?

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.
}
}

AS3 Play contents of a symbol

I've grouped a multiple layer 1 frame actionscript driven animation into a symbol. (simply put, imagine a 1 frame image being tweened by code over a few sec, in this symbol)
Now I'd like to play the contents of this symbol using an event listener.
But
stuff_mc.gotoAndPlay(1); and Test Movie doesn't play a thing (doesn't even show the contents of the symbol (the picture) which can actually be seen on stage).
If I go inside the stuff_mc and Test Scene, it works perfectly..
So how do I play stuff_mc from the stage?
Thanks in advance
It sounds to me like you are using multiple scenes. If that's the case then this is most likely where your problem is. Scenes are generally a bad idea in Flash – Adobe itself admits this.

Flash video player scrubber dragging past progress bar fill

I'm trying to troubleshoot the scrubber for a custom video player and I'm coming across an issue with the scrubber being dragged past the progress bar fill if the flv hasn't fully loaded.
The player is here:
http://mindfilemultimedia.com/stage/portfolio.html
If you play the video you will see that while the flv is still downloading, when you move the scrubber past the yellow progress bar into the white part of the line, the video player will freeze. It is doing that because the user is telling it to seek to a part of the video that has not been fully downloaded yet. What I want it to do is determine if the flv is still downloading and restrict the user to only be able to drag the scrubber up until the width of the yellow progress bar. Right now I have set the code to retrieve the bytesLoaded and bytesTotal and what I want to do is to say something like (in actionscript 3):
if (videoPlayer.bytesLoaded < videoPlayer.bytesTotal) {
var newBounds:Rectangle = new Rectangle(0, 0, (videoPlayer.bytesLoaded/videoPlayer.bytesTotal) * MovieClip(root).SeekBar.SeekProgressBar.width, 0);
MovieClip(root).SeekBar.SeekBarHandle.startDrag(false, newBounds);
}
I am by no means an actionscript person, so that was my attempt at doing what I needed. I have a feeling that it is not working because I'm accessing the classes incorrectly for the progress bar and the scrubber handle, but I am just taking the default classes as the seekbar was a flash components. Well, I can just be completely wrong. Any help here would be appreciated.
Where are you putting this code? It needs to be put somewhere, where it is updated regularly. Depending on what type of video player you were using you could see what events it dispatches and use an event listener to regularly check how much has been buffered. You could also use the enter frame event although you would need to make sure you stopped listening once the buffer is complete as it would add extra overhead on every frame.
As a side note SeekBar and SeekBarHandle should probably be seekBar and seekBarHandle respectively, as it's standard practice to start instance names with a lowercase letter in actionscript.