Is there a way to write a |RtmpSampleAccess command to a NetStream in data generation mode? - actionscript-3

I'm streaming data from a server and passing it into a net stream in data generation mode. I'm successfully wrapping H264 and PCMU to be played back through NetStream, however I need to be able to capture this output from the video display it's on and store it in an image. When using an RTMP server, I'd configure it to send an RtmpSampleAccess command, with true,true for audio and video access allowed. When using RTMFP I'd do the same, send() a RtmpSampleAccess true,true from the peer to allow access.
I believe I need to send in an FLV tag for a script data object to represent the RtmpSampleAccess command, however I can't find any information on what the format of that tag needs to be. I've tried using the OSMF FLVTagScriptDataObject with the objects set to the following combinations:
["|RtmpSampleAccess", true, true];
["|RtmpSampleAccess", [true, true]];
And various attempts at guessing the naming for object parameters (though looking at the protocol docs, I'm not sure there is one).
Could someone out there help me here, would be much appreciated.

Where you put your Netstream into Data Generation mode you add a second Play command. The second one simply plays "a blank" and for some reason this overrides the security error.
ns.play(null);
ns.play(""); //works to avoid all security errors
ns.appendBytesAction(NetStreamAppendBytesAction.RESET_BEGIN);
Then to draw just setup a button to run the draw_VideoFrame function when clicked, or try real-time drawing with something like below (using enterFrame):
vid_Obj.addEventListener(Event.ENTER_FRAME, draw_VideoFrame);
and then create a function like this example.
function draw_VideoFrame (e:Event) : void
{
vid_BMD.draw( vid_Obj ); //draw into a BitMapData variable
}

Related

Consistent Empty Data using MediaRecorderAPI, intermittently

I have a simple setup for Desktop Capturing using html5 libraries.
This includes a simple webpage and a chrome-extension. I am using
Extension to get the sourceId
Using the sourceId I call navigator.mediaDevices.getUserMedia to get the MediaStream
This MediaStream is then fed into an instance of MediaRecorder for recording.
This setup works most of the times, but a few times I see that requestData() on MediaRecorder instance returns blob with empty data consistently. I am clueless as to what can cause a running setup to start misbehaving sometimes.
Some weird behaviour that I noticed in the bad state:
When I try to close/refresh the window it doesn't respond.
The MediaStreamTrack object in Step 2) above is 'live' but as soon as I go to Step 3) it becomes 'muted'.
There's no pattern to it, sometimes it even happens when I request for the MediaStreams the very first time(which rules out the possibility that there could be some dangling resources eating up the contexts)
Is there anything that I am doing wrong and am unaware of? Any help/pointers would be highly appreciated!

simple video chat using as3

I'm trying to make a simple video chat using Flex framework and red5 server. It's an application with 2 video displays. With connection to the server more or less figured out. However, I do not understand how to transfer user1 stream to user2.
Here is functions i use to transfer webcam image to the server and to get the stream.
public function appendStream(connection:NetConnection):void {
myNetStream = new NetStream (connection);
myNetStream.attachAudio(cameraVideo.getMic());
myNetStream.attachCamera(cameraVideo.getCam());
myNetStream.publish("videochat" , "live");
}
public function getStream(connection:NetConnection):Video {
guestNetStream = new NetStream(connection);
video2.attachNetStream (guestNetStream);
guestNetStream.play("videochat");
return video2;
}
As you can see, i am getting my own stream.
Is it possible to solve the problem by flex, or I need programming on the server side?
You dont need separate rooms, simply use unique stream names for each client. The ez way is to create your steam names ahead of time and pass them to your swf via flashvars; that way you dont have to pair them with some other complicated scheme.
For a bit more background in red5, a room is a type of scope and a scope can contain other scopes which includes broadcast scopes, shared object scopes, and rooms. There is no limit on the number of these scopes other than the amount of RAM on the server itself.
You need to have two "rooms" instead of one "videochat". User1 must publish to "videochat1" and stream from "videochat2". Vice versa for user2.
And please remove Flex mention here since there's nothing related to Flex UI framework here

How to load a ByteArray FLV in OSMF?

I'm working on a local application ( it's not a website or nothing related ) and I have various FLVs with a very simple encryptation method by now (just like adding 10 at each byte).
I can load/play them using NetStream.appendBytes() after decrypting, but that happens only after I read all video data it's not streamed.
What I really need is to stream those videos from a remote url, and decrypting while receiving data, using a OSMF based player that I already have built.
I'm lost on how OSMF deals with FLV, otherwise, I would try to create a plugin or something like.
I'd be very thankful if someone point me how to deal with that.
But I'd be happy if someone help me to find a way to load a local file using OSMF, passing a ByteArray value, instead of a url (below). Or even giving me directions to create a OSMF plugin to solve my problem.
videoElement.resource = "video_url/video.flv";
This is my current code just to play my decoded FLV byte array
private function playBytes(bytes:ByteArray):void
{
// detecting it's header
if (bytes.readUTFBytes(3) != "FLV")
{
_text.appendText("\nFile \""+ file +"\" is not a FLV")
return void;
}
bytes.position = 0;
netConnection.connect(null);
netStream = new NetStream(netConnection);
netStream.client = { onMetaData:function(obj:Object):void { } }
video.attachNetStream(netStream);
addChild(video);
// put the NetStream class into Data Generation mode
netStream.play(null);
// before appending new bytes, reset the position to the beginning
netStream.appendBytesAction(NetStreamAppendBytesAction.RESET_BEGIN);
// append the FLV video bytes
netStream.appendBytes(bytes);
}
Interesting post, I'd be interested to see the answer. Looking at something similar myself, though not with a stream, I came across the following.
http://ntt.cc/2008/07/15/bitsreader-read-bits-from-given-bytearray.html
After passing the byte array you can use bits.read(8) of a 10 bit array. Perhaps this would send you down the correct path? Otherwise, I'm thinking you'd need to break it apart and essentially do smaller sections to buffer in order to concatenate all the buffered data...
Just a thought,

How to check for the FLV file existence before playing that using FLVPlayback in Action Script 3?

I'm very new to the Action Scripting, I'm using the FLVPlayback class to play my FLV files.
If I'm trying to play a FLV file which is not existed yet then I am getting a "VideoError: 1000" with message of Unable to make connection to server or to find FLV on server.
I want to check for the FLV file existence using the file URL or path, before playing that FLV by FLVPlayback. Can anybody please suggest a way to do that.
Thanks
The only way to catch the error safely is to listen for the fl.video.VideoEvent.STATE_CHANGE event and act accordingly. Here's a little code snippet on how to do so:
import fl.video.FLVPlayback;
import fl.video.VideoEvent;
import fl.video.VideoState;
var videoPlayer:FLVPlayback;
videoPlayer.addEventListener( VideoEvent.STATE_CHANGE, onVideoStateChange );
/** Bad source **/
videoPlayer.source = "http://www.helpexamples.com/flash/video/caption_video_error.flv";
/** Good source **/
//videoPlayer.source = "http://www.helpexamples.com/flash/video/caption_video.flv";
function onVideoStateChange( evt:VideoEvent ):void
{
var videoPlayer:FLVPlayback = evt.target as FLVPlayback;
switch( evt.state )
{
case VideoState.CONNECTION_ERROR:
trace( 'Connection error' );
/**
* Once you hit this event, you should run some logic to do one or more of the following:
* 1. Show an error message to the user
* 2. Try to load another video
* 3. Hide the FLVPlayback component
*/
break;
default:
trace( 'Player is: ' + evt.state );
}
}
For a full list of possible VideoState constants, visit fl.video.VideoState.
I think you may be able to make use of the stateChange event. One of the possible event types is VideoState.CONNECTION_ERROR and another is VideoState.DISCONNECTED which may also work.
Try giving that a shot.
If those don't work, the only way I can think of would be to either do a HEAD or GET request for the flv before you attempt to load it. Only a successful response would trigger the video loading through the normal method. I don't remember whether Flash supports HEAD requests, but if it does that would certainly be the better option.
If Flash does not support HEAD requests then you may be better off having a simple, server-side script that could verify the existence of the flv before you actually request if. That way you can use a simple GET request without having to retrieve the whole file.
INLINE THINKING
I am just thinking, another possible solution using GET would be to cancel the load as soon as bytesLoaded > 1K (for example), or something like that. As long as you are checking for a size greater than the 404 response you are getting, you should be able to assume the flv is being loaded.

AS3 Loading XML from a different domain

I am trying to load an xml file from wikipedia into my flash movie.
loader = new URLLoader();
loader.addEventListener(Event.COMPLETE, tweetLoaded);
loader.load(new URLRequest("http://en.wikipedia.org/w/api.php?action=query&rvprop=content&format=xml&pageids="+subNum));
loader.addEventListener(IOErrorEvent.IO_ERROR, onIOErrorFunction);
This works fine when the flash file is run locally but when I upload to my domain it does not seem to work. I have read elsewhere that the cross domain rule does not apply to XML files only to images and other media. Is this true? If not is there a work around so that I can load in XML files from domains other than the one the swf is hosted on?
thanks
EDIT:
Okay I am really confused, my program queries both Bing API and the media wiki API. The Bing api call works fine, I can retrieve the XML search results back from it fine. But the wikipedia call does not work (online). I have tried listening for the Security_Error on the wikipedia call but it does not fire.
Does anyone have any ideas? Losing it a bit.
Thanks so much for you help. In the end i used http://pipes.yahoo.com
I created a pipe that took in an ID number then spat out a JSON object with the title of the corresponding wikipedia page.
which you can use here http://pipes.yahoo.com/wikibyid
For anyone else doing this you need to make sure you access the pipe from the yahoo api URL
http://pipes.yahooapis.com/
as this domain has the crossdomain.xml file.
A workaround is setting up a proxy with some server side language, so your swf loads data from your domain. This proxy forwards the request to the real host and returns the response to the swf. From the flash side, this works transparently.
You could make your proxy more or less sofisticated, but it could be as simple as (in php):
echo file_get_contents($_GET['target_url']);
This is just to give you an idea, you might want to validate the target_url parameter.
Have your swf call this php script and pass target_url as a parameter. Something like this:
var url:String = "proxy.php";
var paramVal:String = encodeURIComponent("http://en.wikipedia.org/w/api.php?action=query&rvprop=content&format=xml&pageids="+subNum);
url += "?target_url=" + paramVal;
loader.load(new URLRequest(url));
Note that for php this will require allowing fopen for urls (similar permissions might be neccesary for other server side technologies). Also, keep in mind this will affect your server bandwith consumption.
PS
Bing works because they have a crossdomain policy file in place to allow access to swfs from other domains.
http://api.bing.net/crossdomain.xml
Wikipedia doesn't have a crossdomain policy file that grants you access from other domains, so you cannot connect directly from your swf.