How to find when live RTMP stream stops in ActionScript? - actionscript-3

I've currently got the following code, where streamVideo is an FLVPlayBack component:
streamVideo.addEventListener( VideoEvent.STATE_CHANGE, onVideoStateChange );
streamVideo.isLive = true;
streamVideo.source = "rtmp://mystreamurl";
function onVideoStateChange(evt:VideoEvent):void {
var streamVideo:FLVPlayback = evt.target as FLVPlayback;
switch (evt.state) {
case VideoState.CONNECTION_ERROR:
trace( 'Connection error' );
break;
default:
trace( 'Player is: ' + evt.state );
}
}
This gives me Player is: playing when my stream comes on, but when my stream goes off, I don't get any sort of notification.

I remember playing with a similar issue when playing with Adobe Cirrus and netstreams. I'm not sure if this will work, but try checking to see if the videoDataRate == 0 under your streamVideo's metaData property.

Related

Video event on given second

Need to play the next video, when current video time reaches the given value, but don't know why the event that should get currentTime is not firing at all? Maybe someone has an idea why (obviously the simplest tasks are the ones making most problems)
function setupVideoPlayer() {
var currentVideo = 1;
// i.e. [video url, start time, end time]
var videos = [["1.mp4", 0, 4], ["2.mp4", 3, 7]];
var videoPlayer = document.getElementById('videoPlayer');
// set first video clip
videoPlayer.src = videos[0][0]; // 1.mp4
// Syncrhonization function should come here
videoPlayer.addEventListener('timeupdate', function(e){
if (this.currentTime == videos[currentVideo-1][2]) {
currentVideo += 1;
this.src = videos[currentVideo-1][0];
this.play();
}
}, true);
// It makes sure the seek will happen after buffering
// the video
videoPlayer.addEventListener('progress', function(e) {
// Seek to start point
this.currentTime = videos[currentVideo-1][1];
}, false)
}
I would suggest changing the time check to a > rather than = because the currentTime event isn't an integrer
if (this.currentTime == videos[currentVideo-1][2]) {
becomes
if (this.currentTime > videos[currentVideo-1][2]) {
(or you could convert it to an integrer for the test)
If there are other issues it's worth adding a console.log(this.currentTime) to the event just to see if it's triggering the code

Nullpointer exception in Soundcloud HTML5 Widget API when creating dynamically new player iFrames

I could reduce my problem on a small code snippet. The code creates dynamically an SC player iFrame and displays the ready status. If there is already an iFrame, it removes the old one and creates a new one (runable example on JSFIDDLE):
var player;
var playerId;
var iframe;
var printReady=
function(data)
{
document.getElementById("status").innerHTML = "Ready";
};
function createSoundCloudIframe()
{
document.getElementById("status").innerHTML = "Player not ready";
var contentDiv = document.getElementById("content");
// Remove last Iframe
if(iframe != null){
player.unbind(SC.Widget.Events.READY);
contentDiv.removeChild(iframe);
}
// Create a new Iframe
iframe = document.createElement("IFRAME");
iframe.id = playerId + "ScId";
iframe.src = "http://w.soundcloud.com/player/?url=http%3A%2F%2Fapi.soundcloud.com%2Ftracks%2F41867062&show_artwork=true";
// Append Iframe
contentDiv.appendChild(iframe);
// Show ready status
player = SC.Widget(playerId + "ScId");
player.bind(SC.Widget.Events.READY, printReady);
playerId ++;
};
The code runs fine when it is executed the first time. But when you try it a second time a nullpointer exception (developer console) will be thrown in this method of api.js:
// Uncaught TypeError: Cannot read property 'parentWindow' of null
function s(a) {
return a.contentWindow || a.contentDocument.parentWindow
}
The method which causes the exeption is SC.Widget(iFrameId);
This problem is in my case not solvable with SC.Widget(iFrameId).load(url, options); function and a hiding of the iFrame:
I wrote a google-web-toolkit wrapper for the SC widget api and use this wrapper with other gwt mediaplayer wrappers in a much bigger project. In this project the exception is thrown repeatedly with a delay of milliseconds which slows down everything. The codesnippet above is only a pure javascript reduction of the problem.
I really need a workaround which removes and clean up all dead references in the api.js when the iFrame is removed! I'm looking for such a workaround for month.

Flash as3 show specific movie clip on click

I just started using flash so this might be a simple thing so please be patient.
I'm doing a project were I have a map and you can click the places on the map and the info appears. I could manage to link every button_btn to every info_mc but that would take forever, so I tried to make a function that would read the buttons name and redirect to the info_mc itself. However since the name is being converted to string when I change from name_mc to name_info it is not redirecting. Here is the code.
winterfell_info.visible = false;
map.winterfell_btn.doubleclickEnabled = true;
map.winterfell_btn.mouseChildren = doubleClickEnabled;
map.winterfell_btn.addEventListener(MouseEvent.DOUBLE_CLICK, show_clicked);
function show_clicked(e:MouseEvent):void{
var get_name = e.currentTarget.name;
var open_info_string = get_name.slice(0,-3) + "info";
//I've tried some things here but nothing is working for me.
var open_info = stage.getChildByName(open_info_string);
open_info.visible = true;
}
Any help would be very much appreciated, thank you.
And if you wondering yes its a map for Game of Thrones.
Remove quotes around "open_info_string", as a first measure, and change the capital S in that string to normal one "s", because Actionscript is case sensitive.
var open_info = stage.getChildByName(open_info_string);
Then, if it wouldn't work at once, insert a trace(open_info_string); before you try to reach the movie clip, to find out whether it was cropped correctly.
i've done something similar.. i don't have time to adapt the code, but if you look at what I did here I believe it'll help you. I'm making an array with the instance names of objects on my video player and then created a function which adds the appropriate event listener using a switch case statement.. easiest way to do this in mass, in my opinion.
var buttons:Array = [clicky,pauseBtn,playBtn];
for (var i in buttons)
{
buttons[i].buttonMode = buttons[i].useHandCursor = true;
addEventListner(buttons[i]);
}
function addEventListner(movieClip)
{
movieClip.addEventListener(MouseEvent.CLICK, function(e){
e.stopPropagation();
switch (movieClip.name)
{
case "playBtn" :
youTubeHolder.videoPlayer.playVideo();
videoController.playBtn.visible = false;
videoController.pauseBtn.visible = true;
break;
case "pauseBtn" :
youTubeHolder.videoPlayer.pauseVideo();
videoController.playBtn.visible = true;
videoController.pauseBtn.visible = false;
break;
case "stopBtn" :
youTubeHolder.videoPlayer.seekTo(0);
youTubeHolder.videoPlayer.stopVideo();
break;
default :
trace(movieClip.name+"is not a valid button");
}
});
}

Actionscript 3 Sound ioError Problem

i am having trouble with sound. i am loading it dynamically, url comes from flashvars.
App is working actually but stil gives error, unhandled ioError. but i already handled it.
`
var sound:Sound = new Sound()
try{
sound.load(new URLRequest(req));
} catch(e:IOError){
trace("catch ioerror");
}
sound.addEventListener(IOErrorEvent.IO_ERROR, function(evt:IOErrorEvent):void { trace("error:",evt) } );
sound.addEventListener(Event.COMPLETE, function(e:Event):void{
channel = sound.play(0,int.MAX_VALUE);
});`
Just to rule it out, try commenting out the line channel = sound.play(0,int.MAX_VALUE); perhaps it is this that is throwing the error and not the load, and you have no catch around this.
Try a neater approach in terms of code, might just have issues with your layout and such:
var request:URLRequest = new URLRequest(req);
sound.load(request);
sound.addEventListener(IOErrorEvent.IO_ERROR, _ioError);
sound.addEventListener(Event.COMPLETE, _complete);
function _ioError(e:IOErrorEvent):void
{
trace("File was not found");
_removeListeners();
}
function _complete(e:Event):void
{
channel = sound.play(0,int.MAX_VALUE);
_removeListeners();
}
function _removeListeners():void
{
sound.removeEventListener(IOErrorEvent.IO_ERROR, _ioError);
sound.removeEventListener(Event.COMPLETE, _complete);
}

getting a shared object to expire after browser session in FLASH?

I'm looking for a way to play flash animated content once ( even as the user navigates to different HTML pages with similar flash content) and expire after a set amount of time or after the browser is closed.
I'm aware I could use a shared object for this but can't seem to find info about how to clear them at browser session end.
I am open to using javascript or PHP to assist .
your help is appreciated -
thanks -MW
Instead of using a SharedObject, you could create two simple server-side services: one that maintains the session, and one that exposes the session through a generated XML file that your flash application could use.
The first service would set some session variables and should be called whenever the video is played. It could look like this:
<?php
// start-video.php
session_start();
$_SESSION['hasWatchedVideo'] = true;
$_SESSION['watchedVideoAt'] = time();
?>
The second service is the one that generates the XML response based on the session. It might look like this:
<?php
// flash-config.php
session_start();
// set expiration to 5 min
define(VIDEO_TIMEOUT, 300);
$playVideo = "true";
if($_SESSION['hasWatchedVideo']
&& (time() - $_SESSION['watchedVideoAt']) < VIDEO_TIMEOUT) {
$playVideo = "false";
}
header("Content-Type: text/xml");
echo "<config><playVideo>{$playVideo}</playVideo></config>";
?>
Then from your Flash application, you could do this:
/**
* Called whenever the app is loaded.
*/
protected function init():void {
var u:URLLoader = new URLLoader();
u.addEventListener(Event.COMPLETE, onComplete);
u.load(new URLRequest("http://example.com/flash-config.php"));
}
/**
* Determines whether or not the video should play based on the
* config service response.
*/
protected function onComplete(e:Event):void {
var x:XML = new XML(e.target.data);
if(x.playVideo == 'true') {
playVideo();
}
}
/**
* Should be called either when the video starts playing. I just tied
* it to a user click here.
*/
protected function playVideo():void {
// call the service to update the session
var u:URLLoader = new URLLoader();
u.load(new URLRequest("http://example.com/start-video.php"));
// ... play video code ...
}
I think this approach gives you a bit more flexibility than using a SharedObject. Hope that helps.
UPDATE:
You could use a session cookie in the browser as well. Basically set the expiry date to '0' and the cookie will expire when the user closes the browser. (Note: when I tested this in Firefox, closing the tab was not enough to kill the cookie. The entire browser had to be closed.)
You can use ExternalInterface, or a utility library like this. Using the library, you could have code like this in your flash application:
function playVideo():void {
if(!CookieUtil.getCookie('playvideo')) {
CookieUtil.setCookie('playvideo', 'true', 0);
// ... play video code ...
}
}
Whenever the user closes the browser, the cookie will be cleared. Next time they visit your site, the video will play again. Not sure if this is more inline with what you're look for, but hope it helps.
I modified your code a tad so it will be killed on sesion end ...
the PHP ...
<?php
// flash_php_session_cookie.php
$cookie= "false";
if (isset($_COOKIE["cookie"]))
$cookie= "true";
else
setcookie("cookie", "true", 0);
echo "<config><cookie>{$cookie}</cookie></config>";
?>
the FLASH ...
// the folowing functions handle call coresponding PHP files to handle cookies ...
// re-configure these to the location of the swf ...
var flashConfigURL:String ="flash_php_session_cookie.php";
//Called whenever the app is loaded ...
function initCookieFunc():void {
var u:URLLoader = new URLLoader();
u.addEventListener(Event.COMPLETE, onComplete);
u.load(new URLRequest(flashConfigURL));
}
// Determines whether or not the cookie exists / (assumes theres a text field named T on the stage) ...
function onComplete(e:Event):void {
var x:XML = new XML(e.target.data);
if (x.cookie == 'false') {
T.appendText("cookie doesn't exist yet");
} else {
// cookie exists ...
T.appendText("cookie exists");
}
}
initCookieFunc();
I am going to keep a loose version of the "TIMEOUT"
version as well.
It's great to have an answer to this
Thanks again RJ for the invaluable code
-MW
You'll just have to expire the SharedObject yourself. It's not complicated.
This way your .swf will be completely self contained, not relying on anything external which IMO is a good thing.
package {
import flash.display.Sprite;
import flash.net.SharedObject;
import flash.net.SharedObjectFlushStatus;
public class SharedObjectExample extends Sprite {
private var _so:SharedObject;
private var _now:Date;
private var _last_played:Number;
private static const EXPIRE_TIME:Number = 1000 * 60 * 60 * 24; // 24hrs in msec
public function SharedObjectExample() {
// create a new date for the current time to compare against
_now = new Date;
// create a new shared object
_so = SharedObject.getLocal("application-name", "/");
// try read from the shared object
if (_so.data.last_played) _last_played = _now;
// if no value is set we play the video and set the current time
if (!_last_played) {
// play video here
_last_played = _now.time;
// check if the "cookie" has expired and it's time to play again
} else if ( _now.time - _last_played > EXPIRE_TIME) {
// play video here
_last_played = _now.time;
} else {
// do nothing
}
// and finally, save
saveValue();
}
private function saveValue(event:MouseEvent):void {
// i've removed the code that asks the user for permission if the request for storage is denied
_so.data.last_played = _last_played;
var flushStatus:String = null;
try {
flushStatus = _so.flush(1000);
} catch (error:Error) {
trace("Could not write SharedObject to disk");
}
}
}
}