Simulating video chat using RTMP and Red5 without camera and microphone - apache-flex

I am trying to write an application, which will create load on a Red5 server, similar to a load created when a video chat is going on. Everything should run automatically. So, I am trying to understand how a chat application works. Here's what I found out. Please correct me if I am wrong:
User1 and User2 are chatting. A flex client is written, which will be run in the local of User1 and User2. The flex client User1 and User2 simultaneously will start recording a webcam video and microphone audio. This will create a raw video file (what is the format of this video?) streaming. A stream channel will be established with Red5. In the Flex code I will use NetConnection commands to establish a stream to the Red5 application. The raw audio n video from client side will be streamed to the server and will be saved as an FLV file. FLV file from User1 will be saved as .flv and FLV file from User2 will be saved as .flv. Now, User2 will establish a connection with Red5 to stream in .flv, and User1 will establish a connection with Red5 to stream in .flv. Each time the video is updated at any user side, the corresponding FLV file gets updated. The end user still has the stream open and the new video will now get streamed to the end user. This is how video chat works.
Now, if this is the correct understanding, I have the following questions:
To simulate this chat without webcam and microphone, can I write a flex client to just upload an FLV file from client side to server side, through an established stream? From client side I will use NetConnection to connect to the stream. What kind of server side code should be written to receive that FLV from client to save on the server side? And, this streaming should be similar to the streaming of webcam video.
How can I tell User2 to stream download the same FLV file, which has been uploaded by User1? I mean, suppose I want multiple users to "chat". That means, multiple streams are created. How will each end use know, which particular FLV file to download? Also, how will the end user know, when to start downloading the FLV file? User1 is continuously updating the FLV file, which is getting saved on server side. How will User2 know that the video file has been updated and it is time to stream it down.
Your help is appreciated!!

I suppose you are using Red5 1.0 Final version.
Let's start by answering your question "what is the format of stream video?":
Red5 can stream FLV video and MP3 audio, but it record only FLV (now red5 can stream h264 video).
You asked about using FLV file to replace webcam (...) juste for testing, this is not a good idea, I "don't think" there is a simple way to do it. But you can create many virtual webcams using a third software like manycam.com to help you test your application.
But if you are interested to upload (not publish - no real time) video to red5 server, so you can do it without red5 services, since red5 is a Tomcat server, so you can upload video just like in Java web application, forgot rtmp and use simple java http file upload, then you can broadcast this video.
What kind of server side code should be written to receive that FLV?
If you just need to stream video you don't have to do any think on server side! just create an application empty folder on red5/webapps/your_application_name. But if you need to do more, so you must implement your application.
Next is a collection of commented codes that can help you with this!
Stream Webcam/Microphone to red5 server:
This is an exemple code how publish webcam/microphone from client_1 to red5 server:
var nsOut:NetStream; //Out NetStream
var cam:Camera; //camera instance
var mic:Microphone;//microphone instance
//"nc" is a NetConnection instance connected to red5 application.
nsOut = new NetStream(nc);
//setting the microphone
mic = Microphone.getMicrophone(0);
mic.codec = SoundCodec.SPEEX;
mic.encodeQuality = 4;
mic.setUseEchoSuppression(true);
//setting the microphone
try{
//Create camera instance using Camera.names array to choose the right one!
cam = Camera.getCamera(Camera.names[0]); //Camera.names[1] for second camera and so on.
//Camera Settings
cam.setKeyFrameInterval (15);
cam.setMode (240,180,15,false);
cam.setMotionLevel (35,3000);
cam.setQuality (40000 / 8,0);
}catch(e:Error){
Alert.show("Webcam error!");
}
nsOut.attachCamera (cam); // attach camera to NetStream
nsOut.attachAudio(mic); //attach microphone to NetStream
nsOut.publish ("client_1_stream"); //start streaming
//finaly to show outgoing cam video
var vid:Video = new Video(160,120);
this.addChild (vid);
vid.attachCamera(cam);
Play video Stream:
Now we have a NetStream "client_1_stream" published on Red5 server and ready to be played by other connected user, so this is how client_2 can show this stream:
var nsIn:NetStream; //Incoming NetStream
nsIn = new NetStream(nc);
nsIn.play("client_1_stream");
//finaly to show incoming video
var vid:Video = new Video(160,120);
this.addChild(vid);
vid.attachNetStream(nsIn);
Now you have an idea about publish/play video, for this you don't need any server side codes.
Upload file to red5 server:
This is a good post about uploading file to red5 using java servlet.
Upload file to Red5 server
How can I tell client_2 to stream download the same FLV file,
which has been uploaded by client_1?
In this situation our goal is to send the uploaded file name to client_2 to play it. To complete this, client_1 must call a function on server side that call a function in client_2 code.
client_1 function -- call --> server function -- call --> client_2 function.
On client side we need tow functions, and one function on server side!
The first client function named fileUploadSuccess() call a function on red5 application userFileUploded(fileName), finaly this function find the right user(s) and call the client_2 function named onFileUploadSuccess(fileName).
fileUploadSuccess() -- call --> userFileUploded(fileName) -- call --> onFileUploadSuccess(fileName).
This is a very known technique used on FMS and red5 application, you can find many exemple on line, else I can share some codes with you, if you need more help.
You can also do this using red5 sharedObject, but personally I prefer the first solution.
think you :)

Related

How to use local XML feed for Android TV live channels app

I'm getting a feel for Android TV live channels sample app and Im trying to figure out how and where to change the video src for the sample channels. Can anyone point me in the right direction. Also if it helpls the sample activity takes me to a webpage for the xmltv feed and it says modify {#link com.example.android.sampletvinput.rich.RichFeedUtil#USE_LOCAL_XML_FEED}. If that helps any.
There are two ways to modify the video source for the channels
- Set USE_LOCAL_XML_FEED to true and update the local xml feed with your video.
- Or, if you can host a xml file on a http server, you can upload a feed and change the path for the xml feed from here.

Using ffmpeg in asp.net

I needed a audio conversion library. After already pulling my hair..I have given up on the fact that there is no such audio library out there..every library out there has some or the other problem.
The only option left is ffmpeg which is the best but unfortunately you cannot use it in asp.net (not directly I mean). Every user on the website that will convert a file; will launch an exe?; I think I will hit the server memory max soon.
Bottom Line: I will try using ffmpeg.exe and see how many users it can support simultaneously.
I went to the ffmpeg website and in the windows download section I found 3 different version; static, shared and dev.
Does any one know which would be the best? All packed in one exe (static) or dll's separely and exe small, wrt using it in asp.net?
PS: any one has a good library out there..would be great if you can share.
Static builds provide one self-contained .exe file for each program (ffmpeg, ffprobe, ffplay).
Shared builds provide each library as a separate .dll file (avcodec, avdevice, avfilter, etc.), and .exe files that depend on those libraries for each program
Dev packages provide the headers and .lib/.dll.a files required to use the .dll files in other programs.
ffMpeg is the best library out there from what I have used but I wouldn't recommend trying to call it directly from asp.net.
What I have done, is accepted the upload, stored it on the server, or S3 in my case, then have a worker role (if using something like Azure) and a process that continuously looks and monitors for new files to convert.
If you needed a realtime like solution, you could update flags in your database and have an AJAX solution to poll the database to keep providing progress updates, then a link to download once the conversion is complete.
Personally my approach would be
Azure Web Roles
Azure Worker Role
ServiceBus
The WorkerRole starts up and is monitoring the ServiceBus Queue for messages.
The ASP.NET site uploads and stores the file in S3 or Azure
The ASP.NET site then records information in your DB if needed and sends a message to the ServiceBus queue.
The WorkerRole picks this up and converts.
AJAX will be needed on the ASP.NET site if you want a realtime monitoring solution. Otherwise you could send an email when complete if needed.
Using a queuing process also helps you with load as when you are under heavy load people just wait a little longer and it doesn't grind everything to a halt. Also you can scale out your worker roles as needed to balance loads, should it ever become too much for one server.
Here is how I run ffMpeg from C# (you will need to change the parameters for your requirements)
String params = string.Format("-i {0} -s 640x360 {1}", input.Path, "C:\\FilePath\\file.mp4");
RunProcess(params);
private string RunProcess(string Parameters)
{
//create a process info
ProcessStartInfo oInfo = new ProcessStartInfo(this._ffExe, Parameters);
oInfo.UseShellExecute = false;
oInfo.CreateNoWindow = true;
oInfo.RedirectStandardOutput = true;
oInfo.RedirectStandardError = true;
//Create the output and streamreader to get the output
string output = null; StreamReader srOutput = null;
//try the process
try
{
//run the process
Process proc = System.Diagnostics.Process.Start(oInfo);
proc.ErrorDataReceived += new DataReceivedEventHandler(proc_ErrorDataReceived);
proc.OutputDataReceived += new DataReceivedEventHandler(proc_OutputDataReceived);
proc.BeginOutputReadLine();
proc.BeginErrorReadLine();
proc.WaitForExit();
proc.Close();
proc.Dispose();
}
catch (Exception)
{
// Capture Error
}
finally
{
//now, if we succeeded, close out the streamreader
if (srOutput != null)
{
srOutput.Close();
srOutput.Dispose();
}
}
return output;
}

Meteor package for upload on amazon s3

Which package to use for file uploads to amazon S3 ? knox or collectionFS or any other ?
Is collectionFs ready for file uploads to S3? Or knox is good enough?
Note: in any case i don't want to share my key on the client side. Because of security issue.
2 . Also is there a option where the client file stream can be directly conected to a stream to upload on S3. File is not actually present on the server at any time.
I happen to be looking at this too. CollectionF5 allows file to be send to the server and you can create a handler that sends it to s3 (possibly as blob stream and not a storage). https://github.com/CollectionFS/Meteor-cfs-s3
In the end, you need a place to specify the access key for uploading. If you do not put it in the client side, and you wish the file stream to directory upload on s3, how does the stream get the access?
Possibly you could also take a look at this as alternative: https://www.inkfilepicker.com/

Adobe AIR HTTP Connection Limit

I'm working on an Adobe AIR application which can upload files to a web server, which is running Apache and PHP. Several files can be uploaded at the same time and the application also calls the web server for various API requests.
The problem I'm having is that if I start two file uploads, while they are in progress any other HTTP requests will time out, which is causing a problem for the application and from a user point of view.
Are Adobe AIR applications limited to 2 HTTP connections, or is something else probably the issue?
From searching about this issue I've not found much but one article did indicated that it wasn't limited to just two connections.
The file uploads are performed by calling the File classes upload method, and the API calls are done using the HTTPService class. The development web server I am using is a WAMP server, however when the application is released it will be talking to a LAMP server.
Thanks,
Grant
Here is the code I'm using to upload the file:
protected function btnAddFile_clickHandler(event:MouseEvent):void
{
// Create a new File object and display the browse file dialog
var uploadFile:File = new File();
uploadFile.browseForOpen("Select File to Upload");
uploadFile.addEventListener(Event.SELECT, uploadFile_SelectedHandler);
}
private function uploadFile_SelectedHandler(event:Event):void
{
// Get the File object which was used to select the file
var uploadFile:File = event.target as File;
uploadFile.addEventListener(ProgressEvent.PROGRESS, file_progressHandler);
uploadFile.addEventListener(IOErrorEvent.IO_ERROR, file_ioErrorHandler);
uploadFile.addEventListener(Event.COMPLETE, file_completeHandler);
// Create the request URL based on the download URL
var requestURL:URLRequest = new URLRequest(AppEnvironment.instance.serverHostname + "upload.php");
requestURL.method = URLRequestMethod.POST;
// Set the post parameters
var params:URLVariables = new URLVariables();
params.name = "filename.ext";
requestURL.data = params;
// Start uploading the file to the server
uploadFile.upload(requestURL, "file");
}
Here is the code for the API calls:
private function sendHTTPPost(apiFile:String, postParams:Object, resultCallback:Function, initialCallerResultCallback:Function):void
{
var httpService:mx.rpc.http.HTTPService = new mx.rpc.http.HTTPService();
httpService.url = AppEnvironment.instance.serverHostname + apiFile;
httpService.method = "POST";
httpService.requestTimeout = 10;
httpService.resultFormat = HTTPService.RESULT_FORMAT_TEXT;
httpService.addEventListener("result", resultCallback);
httpService.addEventListener("fault", httpFault);
var token:AsyncToken = httpService.send(postParams);
// Add the initial caller's result callback function to the token
token.initialCallerResultCallback = initialCallerResultCallback;
}
If you are on a windows system, Adobe AIR is using Microsofts WinINet library to access the web. This library by default limits the number of concurrent connections to a single server to 2:
WinInet limits the number of simultaneous connections that it makes to a single HTTP server. If you exceed this limit, the requests block until one of the current connections has completed. This is by design and is in agreement with the HTTP specification and industry standards.
... Connections to a single HTTP 1.1 server are limited to two simultaneous connections
There is an API to change the value of this limit but I don't know if it is accessible from AIR.
Since this limit also affects page loading speed for web sites, some sites are using multiple DNS names for artifacts such as images, javascripts and stylesheets to allow a browser to open more parallel connections.
So if you are controlling the server part, a workaround could be to create DNS aliases like www.example.com for uploads and api.example.com for API requests.
So as I was looking into this, I came across this info about using File.upload() in the documentation:
Starts the upload of the file to a remote server. Although Flash Player has no restriction on the size of files you can upload or download, the player officially supports uploads or downloads of up to 100 MB. You must call the FileReference.browse() or FileReferenceList.browse() method before you call this method.
Listeners receive events to indicate the progress, success, or failure of the upload. Although you can use the FileReferenceList object to let users select multiple files for upload, you must upload the files one by one; to do so, iterate through the FileReferenceList.fileList array of FileReference objects.
The FileReference.upload() and FileReference.download() functions are
nonblocking. These functions return after they are called, before the
file transmission is complete. In addition, if the FileReference
object goes out of scope, any upload or download that is not yet
completed on that object is canceled upon leaving the scope. Be sure
that your FileReference object remains in scope for as long as the
upload or download is expected to continue.
I wonder if something there could be giving you issues with uploading multiple files. I see that you are using browserForOpen() instead of browse(). It seems like the probably do the same thing... but maybe not.
I also saw this in the File class documentation
Note that because of new functionality added to the Flash Player, when publishing to Flash Player 10, you can have only one of the following operations active at one time: FileReference.browse(), FileReference.upload(), FileReference.download(), FileReference.load(), FileReference.save(). Otherwise, Flash Player throws a runtime error (code 2174). Use FileReference.cancel() to stop an operation in progress. This restriction applies only to Flash Player 10. Previous versions of Flash Player are unaffected by this restriction on simultaneous multiple operations.
When you say that you let users upload multiple files, do you mean subsequent calls to browse() and upload() or do you mean one call that includes multiple files? It seems that if you are trying to do multiple separate calls that that may be an issue.
Anyway, I don't know if this is much help. It definitely seems that what you are trying to do should be possible. I can only guess that what is going wrong is perhaps a problem with implementation. Good luck :)
Reference: http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/net/FileReference.html#upload()
http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/net/FileReference.html#browse()
Just because I was thinking about a very similar question because of an error in one of my actual apps, I decided to write down the answer I found.
I instantiated 11
HttpConnections
and was wondering why my Flex 4 Application stopped working and threw an HTTP-Error although it was working pretty good formerly with just 5 simultanious HttpConnections to the same server.
I tested this myself because I did not find anything regarding this in the Flex docs or on the internet.
I found that using more than 5 HTTPConnections was the reason for the Flex application to throw the runtime error.
I decided to instantiate the connections one after another as a temporally workaround: Load the next one after the other has received the data and so on.
Thats of course just temporally since one of the next steps will be to alter the responding server code in that way that it answers a request that contains the results of requests to more then one table in one respond. Of course the client application logic needs to be altered, too.

Audio Cutter in Silverlight

1.
I have created a audio player in silverlight.
within that player user is able to select a portion of song to save as ringtone.
but i got the time duration from .. but I have to cut the partial portion of stream or audio stream and save it to the server dick.
Plz suggest me how I can convert the selected audio time duration into the stream or byte array..?
-- Additional information on this question:
2.
I have created a ringtone audio player in silverlight. Within that user can select a portion which can be cut and save as a audio file.
I am unable to save the stream to the disk.. it is giving following errors:
Error 1. Attempt to access the method failed System IO FileInfo OpenWrite
Plz help
-- Additional information on this question:
3.
What are the use of MediaStreamSample & MediaStreamSource class in silverlight with respect to MediaElement?
Will it help in cutting a portion of audio file in order to create the ringtone out of a song?
If you need to save to the server, then you need to get that data to the server.
Just saving it (as answered) will try to save to the client's machine. What you need to do is upload the data to the server either via a WCF service or an ASHX handler or such. I've done something similar -- uploading MP3 files from a Silverlight client to a WCF service via a Stream, works well.
Next: You need to make sure that whatever splitting process you use accommodates the audio format-- ie you probably just can't split the binary file. What format are you using, mp3?
I've used something called mp3plt, before to split mp3s. You may be able to recompile the source into a Silverlight-compatible library, assuming it's written in something you can use, source here.
Or you can look into the mp3 specs to see if it is possible to just split the binary file, in which case taking the duration to cut (the one the user chose), and multiplying by the bitrate, (kb/s * seconds = kb) will give you the place in the file byte[] you can cut at.
Error 1. Attempt to access the method failed System IO FileInfo OpenWrit, you getting this error coz of security reasons. Before saving to disk you should promt SaveFileDialog to user, and then only save file to disk.

Resources