How to loop FLV seamlessly - actionscript-3

I am playing looped FLVs in the "standard way":
netstream.addEventListener(NetStatusEvent.NET_STATUS, onStatus);
...
public function onStatus(item:Object):void {
if (item.info.code == "NetStream.Play.Stop") {
if (loop) netstream.seek(0);
}
When played through Flash CS 5.5 authoring tool (Test Movie or Debug Movie), the videos loop seamlessly. But! When played in the browser or standalone debug Flash player (both v.11.2.202.233) there is an abnormal pause of about 1 sec before the video "rewinds".
Is this a bug with the latest Flash player?

For People who have the same issue, try changing the aforementioned code to this:
public function onStatus(item:Object):void {
if (item.info.code == "NetStream.Buffer.Empty") {
if (loop) netstream.seek(0);
}
It will get rid of the flicker. If you listen to "NetStream.Play.Stop", it will cause a flicker.
You don't need to embed anything. This works just fine on IOS, Android and PC.

This is a known bug with Flash Player 11+ and AIR 3+. Bug report is here, and you should upvote & : https://bugbase.adobe.com/index.cfm?event=bug&id=3349340
Known workarounds that will create a seamless loop:
1) Embed the video in the SWF. Not ideal, and not possible in some cases.
2) Create dual NetSteam objects and switch between them. An example of the event fired when ns1, the first of two NetStreams objects, reaches it's end:
if (e.info.code == "NetStream.Play.Stop"){
vid.attachNetStream(ns2);
ns2.resume();
activeNs = ns2;
ns1.seek(0);
ns1.pause();
}
Replace ns1 with ns2 on the other event listener. A useless duplication of objects and handlers, but there you go.
3) Use AIR 2.x / Flash Player 10.x (not really a solution at all, except for Linux users)

We noticed this on the transition from Flash 10 to to Flash 11. Flash 10 loops seamlessly, but Flash 11 has a ~1 second stall when calling seek(0) from NetStream.Play.Stop.
Embedding the media in the SWF is not an option for us.
The following code provides a more seamless loop - still not perfect, but much better.
var mStream:NetStream;
var mDuration:Number;
...
addEventListener(Event.ENTER_FRAME, onEnterFrame);
...
function onEnterFrame(e:Event):void
{
if( mStream.time > (mDuration-0.05) )
{
if( mLooping )
{
mStream.seek(0);
}
}
}
function onMetaData(info:Object)
{
mDuration = info.duration;
}
Hope it helps.

I seem to have achieved this using an FLVPlayback component along with a few tips.
What's more, it's running seamlessly on desktop, iPhone 4S and 3GS! (via an AIR app)
_videoFLV = new FLVPlayback();
_videoFLV.fullScreenTakeOver = false;
_videoFLV.autoPlay = false;
_videoFLV.autoRewind = true;
_videoFLV.isLive = false;
_videoFLV.skin = null;
_videoFLV.y = 150;
_videoFLV.bufferTime = .1;
_videoFLV.width = 320;
_videoFLV.height = 320;
_videoFLV.addEventListener(MetadataEvent.CUE_POINT, video_cp_listener, false, 0, true);
_videoFLV.source = "includes/10sec.flv";
addChild(_videoFLV);
With the listener function...
function video_cp_listener(eventObject:MetadataEvent):void {
if (eventObject.info.name == "endpoint") {
_videoFLV.seek(0);
_videoFLV.play();
}
}
Importantly I think you must set the width and height to match your flv file. i.e. no scaling whatsoever.
The flv has a cue point named 'endpoint' added 1 frame before the end of the file (assuming your start and end frame are the same this will be required).I added this using Adobe Media Encoder.

The only way to loop an flv seamlessly is to embed inside the swf. It is converted to a MovieClip and you then handle it with play(), stop(), nextFrame(), prevFrame() etc.
When embedding in Flash Authoring tool (dragging flv file on stage), make sure that you select:
"Embed FLV in SWF..."
Symbol Type : "Movie clip"
All checked : "Place instance on stage", "Expand timeline...", "Include audio"

Related

Expand menu (movieclip) and music in music setting error

I have make a menu in Flash that can expand and there music setting inside.
The music plays when the application starts. To stop the music you must expand the menu and click the music icon.
It's working fine after I open the program and stop the music.
And it's working if I want to play again.
But there's problems after that:
I can't stop the music again and the music playing double in background.
This is my FLA file:
https://drive.google.com/file/d/1DpqdH64kDnI8xN6fBAt3pwi_bIRQ52mT/view?usp=drivesdk
Can anyone tell me the fault of my program? Thanks.
About "music playing double" does your (audio) playback function create a new anything? (eg: = new Sound or = new SoundChannel)? If yes...
Create your audio variables once outside of functions, then use your functions only to stop/start audio playback.
Use new Sound only when loading a new track, once loaded then use one SoundChannel to play/stop that Sound object.
You need a Boolean to keep track of whether a Sound is already playing or not. If true then don't send another .play() command (now gives two sounds to output/speakers).
See if the code logic below guides you toward a better setup:
//# declare variables globally (not trapped inside some function)
var snd_Obj :Sound;
var snd_Chann :SoundChannel = new SoundChannel();
var snd_isPlaying :Boolean = false;
//# main app code
loadTrack("someSong.mp3"); //run a function, using "filename" as input parameter
//# supporting functions
function loadTrack (input_filename :String) : void
{
snd_Obj = new Sound();
snd_Obj.addEventListener(Event.COMPLETE, finished_LoadTrack);
snd_Obj.load( input_filename ); //read from function's input parameter
}
function finished_LoadTrack (event:Event) : void
{
snd_Chann = snd_Obj.play(); //# Play returned Speech convert result
snd_Obj.removeEventListener(Event.COMPLETE, onSoundLoaded);
//# now make your Play and Stop buttons active
btn_play.addEventListener(MouseEvent.CLICK, play_Track);
btn_stop.addEventListener(MouseEvent.CLICK, stop_Track);
}
function play_Track (event:Event) : void
{
//# responds to click of Play button
if(snd_isPlaying != true) //# check if NOT TRUE, only then start playback
{
snd_Chann = snd_Obj.play();
snd_isPlaying = true; //# now set TRUE to avoid multiple "Play" commands at once
}
}
function stop_Track (event:Event) : void
{
//# responds to click of Play button
snd_Chann.stop();
snd_isPlaying = false; //# now set FALSE to reset for next Play check
}

How to Improve FLVPlayback - Reduce Choppy Video

I have a 1920x1080 video playing inside a flash project with the same dimensions, using Firefox. The project is using CC2015, Latest Flash Player, Latest FF. I should note that this project is using locally stored videos.
I'm using AS3, FLVPlayback component, and the videos have been compressed (by production).
Heres the code that uses the playback component
function playVideoByString(source: String): void {
hideTheButtons();
attractTimer.stop();
movie_container = new MovieClip();
addChild(movie_container);
movie_container.x = 0;
movie_container.y = 0;
launchVideo(movie_container, source);
}
function launchVideo(vBox, vFile): void {
attractTimer.stop();
flvPlayer = new FLVPlayback();
flvPlayer.source = vFile;
flvPlayer.skinAutoHide = true;
flvPlayer.skinBackgroundColor = 0x000000;
flvPlayer.width = 1920;
flvPlayer.height = 1080;
flvPlayer.autoRewind = false;
cuePt.time = 0.9;
cuePt.name = "ASpt1";
cuePt.type = "actionscript";
flvPlayer.addASCuePoint(cuePt);
vBox.addChild(flvPlayer);
// adding listeners in here
flvPlayer.addEventListener(MetadataEvent.CUE_POINT, cp_listener);
flvPlayer.addEventListener(fl.video.VideoEvent.COMPLETE, completeHandler);
}
Playback is experiencing some degradation in the form of what looks like frames dropping, or "stutter." The animations look glass smooth when the MP4 is opened in Firefox and played back using FFs player. They also look fine when played in QuickTime (obviously). The video is 30FPS, as is the Flash Project, though from what I understand, FLVPlayback will use the videos encoded frame rate regardless of Flash's FPS.
Is there anything I can do to improve the video playback, and possibly smooth the videos out without loosing quality?

AS3 Preloader doesn't work locally, loaderInfo ProgressEvent.PROGRESS event does not fire

Making a custom AS3 preloader, I noticed that when my SWF is executed locally (file:///) the preloader gets stuck in the loading screen when previewed in a web browser like Chrome.
When executed from a remote server or through the standalone Flash Player, then it works. I noticed other SWF that have preloaders do not have this issue. What I need to change?
this.loaderInfo.addEventListener(ProgressEvent.PROGRESS, preloaderProgress);
function preloaderProgress(event:ProgressEvent):void {
var loadedPercent:Number = event.bytesLoaded/event.bytesTotal*100;
if (loadedPercent == 100){
this.gotoAndStop(2);
}
}
Loading locally goes very fast. Not only you should check if the file is completely loaded using the Event.COMPLETE and not the ProgessEvent but you should also make sure to register your listeners before actually calling load or the file might end up completely loaded before you register your listeners.
Following the example at http://stephenscholtz.com/201110/single-movie-flash-preloading-as3
It seems that there was no ProgressEvent.COMPLETE, but there is a Event.COMPLETE instead, a bit confusing.
I changed my code to the following, (also including some tweaks for right click menu to prohibit the user from right clicking and pressing Play before movie has loaded and such)
//Initialize any variables
var loadedPercent:Number = 0;
//Remove all items from right click Flash Player menu (except Quality, and the mandatory About... & Settings...)
var cxMenu:ContextMenu = new ContextMenu();
cxMenu.hideBuiltInItems();
cxMenu.builtInItems.quality = true;
this.contextMenu = cxMenu;
/* or disable right click menu completely (Flash Player 11.2.202.228 and over) */
/* this.addEventListener(MouseEvent.RIGHT_CLICK, onMouseRightClick);
function onMouseRightClick(event:MouseEvent)
{
return false;
} */
//Disable shortcut keys and window menubar when played from desktop Standalone Flash Player app
if (Capabilities.playerType == "StandAlone" || Capabilities.playerType == "External") {
fscommand("showmenu", "false");
fscommand("trapallkeys", "true");
}
/* Preloader: begin */
//Update loading bar and percent text as SWF loads
function onProgress(e:Event) {
//Get the amount of bytes that have been loaded / bytes total to load
loadedPercent = this.loaderInfo.bytesLoaded/this.loaderInfo.bytesTotal*100;
//Update the text of _preloaderProgress movieclip
_preloaderProgress.text = int(loadedPercent)+"%";
//Update the _preloaderBar amount by scaling horizontally as it loads
_preloaderBar.scaleX = loadedPercent/100;
}
//Go to next frame after everything loads
function init(e:Event) {
gotoAndStop(2);
}
//Attach the events to the stage
this.loaderInfo.addEventListener(ProgressEvent.PROGRESS, onProgress);
this.loaderInfo.addEventListener(Event.COMPLETE, init);
/* Preloader: end */
//Stop to 1st frame and wait until it is loaded
stop();
This will allow the movie to play both remotely and locally with no problems.

Switch language (audio and lyric) seamlessly in Adobe Flash

I’m creating a multilingual flash game with multilingual narrations. Till now i’ve got one language with an audio stream and lyric to accompany it in it’s own timeline controlled by a button on the main timeline to pause and play. I would like to add 2 more languages with audio and own lyric(karaoke style) for each language in this scene. And eventually have buttons on the main timeline that would switch the language(audio and lyric) and seamlessly continue from where the last language left off. Till now I have this action from the main timeline controlling the audio and lyric. englyr being the movie clip, with audio and lyric in it.
toggleButton.addEventListener(MouseEvent.CLICK, toggleClick3);
toggleButton.buttonState = "off";
function toggleClick3(event:MouseEvent) {
if (toggleButton.buttonState == "on") {
englyr.play();
toggleButton.buttonState = "off";
} else {
toggleButton.buttonState = "on";
englyr.stop();
}
}
I’m assuming I should put the other 2 languages as well as their lyric in englyr so that I can disable/mute languages that are not needed to be heard or seen. One problem is I can’t group the lyric and the narration(2 layers) together as a movie clip in that timeline. Therefore cannot disable the 2 other languages that shouldn’t be heard or seen. Any solutions?
It's probably easier to let them both play from code instead of via the timeline.
The first thing to do is to go to the settings of your audioclips in the library, enable "Export for Actionscript" and set a different class name for both your clips. I have named mine "english" and "french".
The following code manages two sounds and changes the language when you press the button of a language that is currently not playing.
var englishClip:Sound = new english(); //load both sounds.
var frenchClip:Sound = new french();
//create the sound and the sound channel.
var myChannel:SoundChannel = new SoundChannel();
var mySound:Sound = englishClip;
//if you want to have lots of different languages it might be easier to just have different buttons instead of one with a state.
englishButton.addEventListener(MouseEvent.CLICK, SpeakEnglish);
frenchButton.addEventListener(MouseEvent.CLICK, SpeakFrench);
//we'll start with having just the english sound playing.
myChannel = mySound.play();
function SpeakEnglish(event:MouseEvent) {
if (mySound != englishClip) { //if the english sound is already playing, do nothing.
var currentPlayPosition:Number = myChannel.position; //save playback position.
myChannel.stop(); //stop playing
mySound = englishClip.play(currentPlayPosition); //resume playing from saved position.
}
function SpeakFrench(event:MouseEvent) {
if (mySound != frenchClip) { //if the French sound is already playing, do nothing.
var currentPlayPosition:Number = myChannel.position; //save playback position.
myChannel.stop(); //stop playing
mySound = frenchClip.play(currentPlayPosition); //resume playing from saved position.
}
This could all be made more compact by having a single function that you pass the appropriate sound to. It would look something like this:
function SpeakEnglish(event:MouseEvent) {
ChangeSound(englishClip);
}
function SpeakFrench(event:MouseEvent) {
ChangeSound(frenchClip);
}
function ChangeSound(newSound:Sound){
if (mySound != newSound) { //if the sound is already playing, do nothing.
var currentPlayPosition:Number = myChannel.position; //save playback position.
myChannel.stop(); //stop playing
mySound = newSound.play(currentPlayPosition); //resume playing from saved
}
And that should solve the problem, i hope that helped :)
Resource: http://www.republicofcode.com/tutorials/flash/as3sound/

Play sound at certain playProgress or videoTime with greensock?

I'm using greensock LoaderMax to load video files and sound files. I've copied as much code as is available to me. A video (s9) is playing and at a certain percentage through the video, I need to play another sound.
if(s9.playProgress > .1) // This is what I can't get to work
{
s12_sound.playSound(); //This sound won't play at .1 playProgress
}
s9.content.visible = true;
s9.playVideo();
stop();
s9.addEventListener(VideoLoader.VIDEO_COMPLETE, play_s9_loop); //This plays a video once s9 is done.
function play_s9_loop(event:Event):void
{
s9.content.visible = false;
s9_loop.content.visible = true;
s9_loop.playVideo();
}
I'm guessing you just can't do an if() on playProgress? Furthermore, I suck at AS3.
You should be able to just listen for the INIT event on the video (which typically means it has loaded enough to determine the duration of the video) and then add an AS cue point.
//...after you create your VideoLoader...
myVideoLoader.addEventListener(LoaderEvent.INIT, initHandler);
myVideoLoader.load();
function initHandler(event:LoaderEvent):void {
myVideoLoader.addASCuePoint( myVideoLoader.duration * 0.1, "myLabel" );
myVideoLoader.addEventListener(VideoLoader.VIDEO_CUE_POINT, cuePointHandler);
}
function cuePointHandler(event:LoaderEvent):void {
trace("Hit the cue point " + event.data.name);
s12_sound.playSound();
}
Also make sure that you preload that s12_sound so that it's ready to play when you need it. Otherwise, you can call playSound() all you want and it ain't gonna happen :)
I haven't used this class before but after reading the docs it looks like you can do something like this:
http://www.greensock.com/as/docs/tween/com/greensock/loading/VideoLoader.html
var mid:Number = s9_loop.duration/2; //get the midpoint using the duration property
s9_loop.addASCuePoint(mid, "middle") //using addASCubePoint to add a cuepoint to the midpoint of the video
s9_loop.addEventListener(VideoLoader.VIDEO_CUE_POINT, handleMidpoint); //listen for the cuepoint
Inside the handler function
protected function handleMidpoint(e:Event):void{
//play your sound
}