AS2: Record & Save Audio To Server With Flash Media Server

Download Example Files

The other day I posted a tip on how to set up Flash Media Server Developer Edition locally on your PC. To reiterate, I'm by no means an expert with Flash Media Server and this was the only test I had done with it, but I figured I'd show how to record some audio using your microphone and FMS and save it on to the FMS server as an .flv file. Let's take a look at the code:

Actionscript:
  1. stop();
  2.  
  3. var count:Number          = 0;
  4. var timestamp:Date    = new Date();
  5. var nc:NetConnection       = new NetConnection();
  6.  
  7. nc.connect("rtmp://localhost/audiotest/samples");
  8.  
  9. var ns:NetStream          = new NetStream(nc);
  10. ns.setBufferTime(2);
  11.  
  12. var mic:Microphone    = Microphone.get();
  13. mic.setRate(22);
  14.  
  15. ns.attachAudio(mic);
  16.  
  17. ns.onStatus = function($info:Object):Void
  18. {
  19.     trace($info.code);
  20. };
  21.  
  22. // record the audio to the stream
  23. function recordAudio():Void
  24. {
  25.     var fileName:String = String(timestamp.getTime() + (count++));
  26.    
  27.     ns.publish(fileName, "record");
  28. }
  29.  
  30. // stop the recording of audio to the stream
  31. function stopRecordingAudio():Void
  32. {
  33.     ns.publish(false);
  34. }
  35.  
  36. // plays back the audio that was recorded
  37. function playRecordedAudio():Void
  38. {
  39.     ns.play(currentFileName);
  40. }
  41.  
  42. // record button
  43. recordBtn_mc.onRelease = function():Void
  44. {
  45.     recordAudio();
  46. };
  47.  
  48. // stop button
  49. stopBtn_mc.onRelease = function():Void
  50. {
  51.     stopRecordingAudio();
  52. };
  53.  
  54. // play button
  55. playBtn_mc.onRelease = function():Void
  56. {
  57.     playRecordedAudio();
  58. };

As you can see, I'm still making a connection to my localhost on my PC. This example assumes that you have an "audiotest" folder in your "applications" folder in FMS (refer to the tip here to see how to set up your file structure). Inside of that folder you have your "streams" folder and in there you have a folder called "samples" which is the destination directory that the .flv files will be saved to when you stop recording.

After that we have our standard code for connecting to the stream and getting the microphone. The next thing I want to go over is the recordAudio() method. I'm creating a random filename using the Date object to try to make the filename as random as possible. I was also adding a variable that I was increasing by one each time to the end of the filename as for some reason when I tried this out originally the filename that was being created was the same every time. By adding count to it, I ensure that during that users session the filenames created won't be the same. The idea here is that you'll have multiple users on the site at the same time using the service so creating the files using the date makes the chance of it being named the same very small. For the current users session, you'll increase by count to ensure that that user's filenames don't mix up as well. Ideally, you'd want to create a safer naming convention to prevent the possibility of creating the same filename for multiple users, but for this example this will suffice.

The last thing we want to note about the filename is that it does not end in the extension .flv. Just like I stated in the tip, you don't need to add the extension to the end of the filename as FMS automatically saves it out as an .flv file.

If you want to convert your .flv to an audio format for later playback, you're opening up a whole pandora's box of issues and you'll be on your own in trying to figure that out. Flash Media Server uses the NellyMoser codec to encode the audio and it's close to impossible to extract the audio unless you a) want to pay about $7,500 to NellyMoser to extract it or b) use a third party command line tool which, from my research, is a pretty hit or miss process.

Saving the file as an .flv on the server (or your hard drive in the "samples" folder if you're following this example) should suffice enough in that you can later play back the .flv file in Flash. With a combination of slick Flash programming and some server-side scripting you can make a nice little application that captures the audio, saves it to the server, saves the filename in the database, and you can later retrieve it for playback.

Here is a blog post that may help you out with some of this audio recording and converting to a different file format: Andrew Paul Simmons' Post

If you found this post useful, please consider leaving a comment, subscribing to the feed, or making a small donation.

51 Comments

Well done - however, the FLA in your zip seems to be corrupt or something - I cannot open it... have tried opening with Flash 8 and Flash CS3.

geronimofo,
I tried it on two separate computers and both worked fine for me. Maybe try downloading it again?

Hi,

thanks for the source, it works great. There are just minor changes to do, you don't play the correct filename when listening to the audio...

ns.publish(fileName, "record");

VS

ns.play(currentFileName);

However, thank you that was very usefull :)

Yeah, sorry about that, I had a currentFileName variable that I was setting in another example I was working on and I dumbed the file down for posting here and forgot to remove that in the play method. Thanks for pointing that out!

Don't you need to place a video instance on the stage, or something to attach the NetStream to?

I couldn't get your example to work until I placed a video instance on the stage, assigned it an instance name of "Video" and inserted the following code:

video.attachVideo(ns);

Afterwards, voila! Worked like a champ.

Thanks for the tutorial!

mrwizzer, this example is dealing with audio, not video.

Hi Matt,

I was playing around with this example and can't figure out how to get the audio to play with the newly created file.

I can get the audio to play if I hardcode one of the files created into the ns.play value. If you could point me in the write direction that would be great (or update the example for my lazy but ;) ).

Not a coder myself, I can muddle about it alright. More for testing the Flash Media Server (which was not had to setup).

Cheers and Thanks!

Thanks, I realize that. But without something to attach the NetStream to, (for example a video instance), the code doesn't work. At least it didn't for me until I added that instance, which I just left off the stage.

hmm, thats odd, because you are attaching the netstream to an instance of your microphone, not a video instance, so you should be ok. i did this a while ago, but from what i remember, it worked fine for me and nobody else has posted any issues with the code.

if anyone else is having the same issue, i can revisit and see if i can fix it up.

I can get it to record audio fine with the current example. The only issue I have is it doesn't playback the audio (I can get it to play it back if I hardcode the filename).

I have no issues with capturing the audio stream, I just can't get it to play back the current file (I can get it to play if I hardcode the file name of one of the previous audio streams).

Am I doing something wrong, I noticed the other comment about the issue but wasn't sure if it was fixed already in the example or if I am doing something wrong?

Cheers and thanks for the example, it was exactly what I was looking for on the recording side.

Yes, that's precisely the problem I was running into. I could capture the audio just fine, (I could see the new file appear on the Flash Media Server in the appropriate folder). But playing it back didn't work.

That's why I tried the attaching to video route. I don't know if that's the recommended way to go, but it worked for me.

Regardless, thanks again for a great tutorial. Really came in handy. Keep up the good work!

John,
I vaguely remember having the same problem. The way I remedied this (from what I can remember) is that I had created a variable called currentFileName (right below the count variable up top) and set that in the record function after dynamically making that fileName there (and just appended .flv to it).

As you can see in the play function, I accidentally left the currentFileName variable in there when publishing this even though I had taken that functionality out. Hopefully that makes sense and helps you out.

Hey,

Thanks for the reply, I cheesed out and just hard coded the record and play back file names. Since I only needed it for a quick demo it doesn't matter if the file is over written each time some one records.

I changed the code from:

function recordAudio():Void
{
var fileName:String = String(timestamp.getTime() (count ));

ns.publish(fileName, "record");
}

To:

function recordAudio():Void
{

ns.publish("audiotest", "record");
}

and I changed the play back to:

function playRecordedAudio():Void
{
ns.play("audiotest");
}

This will save the audiotest.flv to the streaming server and plays it back correctly.

Thanks again!

Cheers

I'd have to look back over the code again, but there may be an issue with declaring the variable "fileName" inside a function and then calling to it outside of the function later.
Maybe try defining the variable at the top of the code before it gets called in any of the functions.

mrwizzer, look at my comment two up from yours, thats precisely what i told John From to do :P

Thanks! I did fix it today and using your suggestion (define outside the function) it worked perfectly, here is the updated code:

stop();
var count:Number = 0;
var timestamp:Date = new Date();
var currentFileName:String
var nc:NetConnection = new NetConnection();

nc.connect("rtmp://blah.blah.blah:1935/audiotest/samples");

var fileName:String = String(timestamp.getTime() (count ));
var currentFileName:String = String(fileName);

var ns:NetStream = new NetStream(nc);
ns.setBufferTime(2);

var mic:Microphone = Microphone.get();
mic.setRate(22);

ns.attachAudio(mic);

ns.onStatus = function($info:Object):Void
{
trace($info.code);
};

// record the audio to the stream
function recordAudio():Void
{

ns.publish(fileName, "record");
}

// stop the recording of audio to the stream
function stopRecordingAudio():Void
{
ns.publish(false);
}

// plays back the audio that was recorded
function playRecordedAudio():Void
{
ns.play(currentFileName);
}

// record button
recordBtn_mc.onRelease = function():Void
{
recordAudio();
};

// stop button
stopBtn_mc.onRelease = function():Void
{
stopRecordingAudio();
};

// play button
playBtn_mc.onRelease = function():Void
{
playRecordedAudio();
};

p.s. sorry about the spam of comments, I didn't think they actually got added.

no problem.

That's one way of doing it. Glad it worked out.

Hi there,

I've found your example really helpful. But I'm having a hard time converting the code to AS3. Would you maybe be interested in posting an example of how it would work in AS3?

Hi Jenny,
Your comment got filtered as spam for some reason so I apologize I didn't get to it sooner.

Anyway, I can't say I've worked with FMS in AS3 so I'm not of much help there, but what parts of the code are you having trouble converting? Maybe we can step through the parts you're having trouble with and figure it out.

Hi, great article! i just wanna know if its possible do this locally without FMS ? Thanks a lot!

As far as I know Christian, no. You need a server app like FMS or Red5.

Nice tutorial - regarding converting the FLV to MP3. Is there any way to stream directly to MP3? I am trying to write an app that will allow people to records these audio clips and then take them and put into a podcast (which would point to the Mp3). Can you point me in the right direction?

Hey Rob,
As far as I know, there is no way to do this without 3rd party software that gets pretty expensive as I talked about in the article. To be perfectly honest, I don't even know how to do it with a 3rd party software either or which one to use, so I apologize that I cannot be of any help. I'd start with the Nellymoser codec and work from there. I'm not an audio aficionado or an FMS aficionado by any means, so you may also want to try contacting Graeme Bull who is really good with FMS to help you. His site is at http://fmsguru.com/. Hope that helps somewhat.

I'm afraid I can't open the .fla either. I have tried opening the file in both Flash MX & Flash 8. Has the zip been corrupted?

Larnibus,
I d/l and opened the FLA just fine. Is anyone else having this issue?

Moyea has an audio SDK which is fairly inexspensive. The SDK allows you to run the tool via command line. I took that and wrote a web service that I call right after I stream up the FLV to the FMS. The web service then executes the Moyea command line and converts it to MP3. Of course you need to make sure the FMS and web service are on same machine (or has access to the folder where the FLV application sits)

It also produces an exit code so you know if it succeded.

Web Service Code:

using System;
using System.Web;
using System.Web.Services;
using System.Diagnostics;
using System.Configuration;
using System.Web.Services.Protocols;
using System.IO;

[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class FLVConvertor : System.Web.Services.WebService
{

[WebMethod]
public string FLV2MP3(string FLVFileName) {
string FMSPath = ConfigurationSettings.AppSettings["FMSPath"];
string FMSApplication = ConfigurationSettings.AppSettings["FMSApplication"];
string FMSAppInstance = ConfigurationSettings.AppSettings["FMSAppInstance"];
string FLVFolderPath = FMSPath FMSApplication FMSAppInstance;
string executable = ConfigurationSettings.AppSettings["FLV2MP3Exe"];
string args = "\"" FLVFolderPath FLVFileName "\" -out \"" FLVFolderPath FLVFileName ".mp3\" -fmt mp3 -ac 1 -asr 44100 -abr 64000";
//string args = "\"" FLVFolderPath FLVFileName "\" -out \"" FLVFolderPath "test" ".mp3\" -fmt mp3 -ac 1 -asr 44100 -abr 64000";
int ExitCode;
try
{
Process process1 = new Process();
//process1.StartInfo.WorkingDirectory = ConfigurationSettings.AppSettings["FLV2MP3ExeFolder"];
process1.StartInfo.UseShellExecute = false;
process1.StartInfo.CreateNoWindow = true;
process1.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
process1.StartInfo.FileName = "\"" ConfigurationSettings.AppSettings["FLV2MP3ExeFolder"] "\\" executable "\"";
process1.StartInfo.Arguments = args;
process1.StartInfo.RedirectStandardOutput = true;
process1.StartInfo.RedirectStandardError = true;
process1.Start();
process1.WaitForExit();
ExitCode = process1.ExitCode;
StreamReader srOutput = process1.StandardOutput;
StreamReader srError = process1.StandardError;
String CmdOutput = srOutput.ReadToEnd();
String CmdError = srError.ReadToEnd();
srError.Close();
srOutput.Close();

//ExitCodes for FLV Audio SDK Convertor
//1 bad command line parameters
//2 I/O error
//3 bad encoding parameters
//8 memory mapping error
//9 dead lock detected
//10 encoding failed
//other unspecified error

return (ExitCode.ToString()) ":" CmdOutput ":" CmdError " Success:" process1.StartInfo.FileName " " args;
}
catch
{
return "error tried doing:" ConfigurationSettings.AppSettings["FLV2MP3ExeFolder"] "/" executable " " args;
}
}

}

Hey Rob,
Thanks for posting that. I've had no need to go further with this example because the project never materialized and to be honest a lot of the stuff you wrote is over my head, but hopefully someone who needs it can use it in the future so its always good to get the info stored here for future reference. Thanks again.

If people are desparate for an open-source flv->mp3 coverter, they should try ffmpeg which can convert nellymoser to any other format.

I've designed an application that does voice analysis at work from recorded .flv's on fms. The problem is that we can't get FMS to call the converter, it has to be called via php or another server scripted language.

Thanks for the guide! It helps me a lot on my project!
Now I'll try to integrate this to the video~

Hey, thanks for the post, it was EXTREMELY helpful.

Now I'm trying to play an mp3 file simultaneously whilst the user sings (karaoke style). Problem is that the outputted stream plays the current track + microphone input.

What's the required technique in order to just record the mic input? Is there such thing as "play the mp3 file on the 1st channel and the mic on 2nd channel", so that only the 2nd channel could be saved?

Hope there's a quick answer... thanks a lot!

Sebastian,
I'm glad this post helped, but to be perfectly honest with you I haven't touched FMS since and have no idea how to do any of the stuff you're asking for :\ you should take a look (and maybe ask) at the http://fmsguru.com/ site, he has some great info on FMS and works with it on a regular basis.

Hey Matt, thanks for the tip buddy. FMSguru seems to be the right place. But once again, thanks for your contribution.

no problem, i apologize that I couldnt help more than that, though :(

I have another question, may be you can help.

Have you ever installed an SDK server-side? How is it done? And once that it's installed, how do you tell de SDK to convert the .flv file residing in the FMS?

Thanks!

Sebastian.

Sebastian,
Sorry, no can do there either. All I ever did was download the developer version onto my local machine and just followed the directions for using that, i've never actually had to install or really deal with FMS otherwise :\

Hi Matt,

That's ok, I found out that you can actually install a FLV Audio Converter SDK on a VTN or dedicated server, through the Apache shell command line.

And to communicate between the SDK and the FMS, apparently you can use a server-side scripting program like PHP, to run the FLV Audio Converter on the fly, pass some parameters to run on the SDK, and once the mp3 file has been successfully created, use PHP once again to move it onto another location on the server.

It is quite a trip if you think about it, to end up using Actionscript, a FMS, an FLV Audio Converter, a VTN or dedicated server and PHP just to accomplish a Karaoke-like application.

Once I accomplish this project, I will post an article on my blog called Mobile Blab, and mention your article if you don't mind.

Cheers!

Sebastian.

Sebastian,
All the server stuff is WAY beyond me :P And sure, i'd love it if you posted an article and linked here, by all means...

Hi,

I have to record microphone input and sound card object together as a single file.my requirement is i have to play karaoke from a list and will sing using microphone.So have to record both sounds together.Microphone recording working fine for me.But no idea how to record the playing sound object,ie how to access the sound card also.Please help me if you can.

Turns out Moyea is using ffmpeg in violation of GPL : http://roundup.ffmpeg.org/roundup/ffmpeg/issue926

Hi,

i had used the following code to record sound from flash .
it is working fine in our LAN. But, when i hosted in an public IP it is not recording any sound ..

can any one please help me that any solution is there to solve this problem.

BELOW IS THE CODE THAT I USED....

stop();

var count:Number = 0;
var timestamp:Date = new Date();
var nc:NetConnection = new NetConnection();

nc.connect("rtmp://localhost/audiotest/samples");

var ns:NetStream = new NetStream(nc);
ns.setBufferTime(2);

var mic:Microphone = Microphone.get();
mic.setRate(22);

ns.attachAudio(mic);

ns.onStatus = function($info:Object):Void
{
trace($info.code);
};

// record the audio to the stream
function recordAudio():Void
{
var fileName:String = String(timestamp.getTime() + (count++));

ns.publish(fileName, "record");
}

// stop the recording of audio to the stream
function stopRecordingAudio():Void
{
ns.publish(false);
}

// plays back the audio that was recorded
function playRecordedAudio():Void
{
ns.play(currentFileName);
}

// record button
recordBtn_mc.onRelease = function():Void
{
recordAudio();
};

// stop button
stopBtn_mc.onRelease = function():Void
{
stopRecordingAudio();
};

// play button
playBtn_mc.onRelease = function():Void
{
playRecordedAudio();
};

Thanks in advance...

Aditya Kiran

@Aditya: you're trying to use localhost on a live site which will not work. you have to replace the url in the connect method with the one to the live site.

When I try to record, it works and i see the .flv file but it's only 1kb. i dont know why. im guessing its not recording everything.
this is the output statement when i press the buttons:

When i press record I get:

NetStream.Publish.Start

When I press Stop i get:

NetStream.Record.Start
NetStream.Unpublish.Success

When I press play I get:

NetStream.Failed

the .flv's turn out to be 1kb

so, how do you limit the recording session, let's say only allow two mins max of recording time? thx.

Hi,
I'm using the above code for recording a sound FMS3.5. Is there any way to put the "time limit" or "size limit" for recording. (e.g.:" i want to stop the recording after 3 sec. or on 100kb, is it possible in this code ?) I'm trying very hard but not getting solution. Can anyone give me solution.

Hi everyone, very nice information.
I am trying to adapt it to record directly to the Flash media Server. Can anyone help me on that. What would be my next steps.
Thank you in advance,
Sukhrob

[...] Schnüffel, Schnüffel [...]

Hi everyone,

if your code doesn't work, please make sure on whether you define correct flash media server path.

You have to create a folder under "applications" folder of FMS Server, such as "audiorecord" then give it path name as below.

nc.connect("rtmp://localhost/audiorecord/audio");

Can this code be modified to record & save movieclips or keystroke-controlled animations? Does the Flash Media Server even allow for this?

I am able to record but i couldn't playback the recorded voice. Please help. I have a red % server installed on my machine.

I could play the swf only when it is saved on the desktop. when i save the file in any of the local disks, the swf doesn't show the flash settings pop up. please help.

Leave a comment

(required)

(required)