Hardware, programming and astronomy tutorials and reviews.

Audio recording in Django apps with flvar

flvar is a flash applet working with a media server and allows users to record audio clips on a website using it.

In a site I'm working on there must be a feature that would allow recording audio and listening to refference recordings. I had to add a flash recorder and player for audio. For recording I've got flvar (non-free), and for playing flowplayer. Using flowplayer isn't a problem - just give him the url to the file. Recording is more complicated as it works with a media server. I used Red5 under Linux.

Installing Red5 under Linux

Check if Red5 is in your distribution repository. If not we have to compile it. To do this install jdk and ant. After that download Red5 package or SVN code:
svn export http://red5.googlecode.com/svn/java/server/trunk red5
To compile it execute in the Red5 folder:
ant prepare
ant dist
That should create a dist folder with compiled and ready to use media server. To run in execute: ./red5.sh.

Configuring Red5 for Flvar

The media server has a folder called webapps. It contains all media apps with their configs. In the flvar package you will get preconfigured apps. Just copy contents of Files to upload to your media server (Red5) to webapps and that's it. The audiorecorder app will be used by the flash applet. All flv files will be stored also in it.

Using flvar with Django

If you got a binary applet only then you have to do a bit of url mapping, as the widget seems to have hardcoded filenames for config/save and language files. For example for config file it will try to call "./avc_settings.php" url. But we don't need that PHP to make it work.

So here is a very basic app for recoding audio files. Copy contents of Files to upload to your website to site_media/recorder of you Django project. Now create an application for recording. I called it recorder, and I've mapped some URLs that are required for it to work:
(r'^recorder/?$', direct_to_template, {'template': 'recorder/flash_recorder.html'}), # show the flash applet
(r'^recorder/translations/en.xml$', direct_to_template, {'template': 'recorder/en.xml'}), # lang file
(r'^recorder/avc_settings.php$', 'recorder.views.return_config'), # settings
(r'^recorder/save_audio_to_db.php$', 'recorder.views.save_to_db'), # save action

/recorder/ view will show a HTML template with the flash recorder. Under /recorder/translations/en.xml I've mapped it default language file, and /recorder/avc_settings.php is pretending to be the config file. Saving a recording will call a view mapped under /recorder/save_audio_to_db.php.

Now copy translations/en.xml to templates folder under recorder/en.xml. Create also recorder/flash_recorder.html template:
	function btSavePressed(streamName,streamDuration,userId,recorderId){
		//this function is called when the SAVE button is pressed and it is called with 4 parameters: 
		//streamName: the file name of the new audio recording on the media server including the .flv extension
		//streamDuration: duration of the recorded audio file in seconds but accurate to the millisecond (like this: 4.322)
		//userId: the userId sent via flash vars or avc_settings.php
		//recorderId: the recorderId sent via flash vars, to be used when there are many recorders on the same web page
<div style="text-align:center;">
	<object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=8,0,0,0" width="320" height="140" id="audiorecorder" align="middle">
	<param name="allowScriptAccess" value="sameDomain" />
	<param name="bgcolor" value="#eeeeee" />  
	<param name="movie" value="/site_media/flvar/audiorecorder.swf?userId={{ user.id }}&recorderId=123" />
	<embed bgcolor="#eeeeee"  src="/site_media/flvar/audiorecorder.swf?userId={{ user.id }}&recorderId=123" width="320" height="140" name="audiorecorder" allowScriptAccess="sameDomain" type="application/x-shockwave-flash" pluginspage="http://www.adobe.com/go/getflashplayer" />

Where userId is the ID of user using the recorder (login required in my case), and recorderId I use for the object ID to which the recording is associated with (static in this example).

Now the view that will return the configuration. It's a key=value string joined with & character:
def return_config(request):
    Return the config for the flash recorder
    This should be a nicely editable dictionary
    return HttpResponse('donot=removethis&connectionstring=rtmp://localhost/audiorecorder/&codec=1&soundRate=10&maxRecordingTime=120&userId=%s' % str(request.user.id))
When recording is saved you will get all data via POST request (user id, recorderId, filename etc.):
def save_to_db(request):
    recording save action called by the flash applet
    print request.POST
    return HttpResponse('ok')
And thats it. Now go to /recorder/ to use the widget:
flvar in django

Replaying audio files

When recording is saved you need to save to the DB the filename and other data. Then you can construct a URL for the player. Recorded files must however be accessible through the HTTP server (alias / document_root or other configuration, symlink in site_media etc.)

Django web framework tutorials, 23 May 2011,

Comment article