Nagrywanie audio w aplikacjach Django za pomocą flvar

W serwisie, nad którym teraz pracuje ma być dostępny moduł pozwalający nagrywać klipy audio i słuchać nagrań wzorcowych. Do integracji dostałem flashowy widżet flvar, a do odtwarzania wybrałem na chwilę obecną flowplayer. Użycie odtwarzacza to nie problem. Widżet nagrywający jest już jednak bardziej złożony bo wymaga serwera mediowego (media server) obsługującego i zapisującego napływające nagranie. Ja wykorzystałem Red5 pod Linuksem.

Instalacja i konfiguracja Red5 pod Linuksem

Warto sprawdzić czy przypadkiem Red5 nie jest dostępny w repozytorium, ale z tego co zdążyłem się zorientować - nie w każdej dystrybucji jest dostępny jako pakiet. W takim przypadku musimy pobrać źródła i skompilować. Jako zależności musimy zainstalować trochę Javy: jdk oraz ant. Mając te pakiety możemy zabrać się za Red5, pobieramy kod z repozytorium (lub pakiet ze strony projektu):
svn export http://red5.googlecode.com/svn/java/server/trunk red5
Następnie w katalogu z kodem wykonujemy:
ant prepare
ant dist
Co powinno skompilować serwer Red5. Stworzony zostanie katalog dist zawierający gotowy serwer. Uruchamiamy go odpalając plik ./red5.sh.

Konfiguracja Red5 dla Flvar

W katalogu z serwerem znajdziemy katalog webapps zawierający wszystkie aplikacje jakie są dostępne w obrębie tego serwera. Wraz z widżetem flvar dostajemy gotowe aplikacje dla serwerów mediowych, w tym dla Red5. W paczce znajduje się katalog Files to upload to your media server (Red5) a w nim katalog audiorecorder, który kopiujemy do webapps w Red5. Możemy odpalić serwer i gotowe.

Współpraca Flvar z Django

Mając binarny widżet bez dostępu do źródeł trzeba się w Django trochę zabawić z mapowaniem adresów URL jako iż widżet ma na sztywno wbitą ścieżkę do plików językowych, jak i nazwę/ścieżkę do pliku konfiguracji... avc_settings.php :)

Do np. site_media/recorder kopiujemy zawartość katalogu Files to upload to your website (z paczki flvar). Następnie tworzymy aplikację django do obsługi nagrywania. Ja nazwałem ją recorder. Dla aplikacji tej mapujemy adresy URL:
(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

Mamy zmapowany widok /recorder/ wyświetlający szablon HTML z flashowym widżetem, a także plik językowy dla niego pod /recorder/translations/en.xml. Konfiguracja to /recorder/avc_settings.php (choć PHP to my tu nie mamy). Przy zapisie nagrania zostanie wywołany widok zmapowany pod /recorder/save_audio_to_db.php.

Do katalogu z szablonami kopiujemy translations/en.xml jako recorder/en.xml. Tworzymy także szablon flash_recorder.html z kodem:
<script>

	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

		

		alert("btSavePressed("+streamName+","+streamDuration+","+userId+","+recorderId+")");

		}

</script>

<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" />

        </object>

</div>

Gdzie userId przypisujemy ID obecnie zalogowanego użytkownika. Pod recorderId ja ustawiałem ID obiektu (newsa, artykułu), którego nagranie dotyczy. Przekazywanie tego parametru pozostawiam to już zależy od twojej aplikacji i potrzeb.

Teraz widok konfiguracji. Sama konfiguracja to ciąg klucz=wartość łączona za pomocą &. Najprostszy przypadek to:
@login_required
def return_config(request):
    """
    Return the config for the flash recorder
    This should be splitted to some nicely editable dictionary
    """
    return HttpResponse('donot=removethis&connectionstring=rtmp://localhost/audiorecorder/&codec=1&soundRate=10&maxRecordingTime=120&userId=%s' % str(request.user.id))
Przy zapisie nagrania dane o nazwie pliku, czasie trwania nagrania, ID użytkownika i obiektu będą wysłane POSTem na zmapowany widok:
@login_required
@csrf_exempt
def save_to_db(request):
    """
    recording save action called by the flash applet
    """
    
    print request.POST
    return HttpResponse('ok')
I gotowe. Wystarczy wejść na /recorder/ by móc korzystać z widżetu:
flvar w django

Odtwarzanie nagrań

Przy zapisie nagrania musimy zapisywać dane o nim w bazie danych (nazwę pliku i powiązane ID użytkownika/obiektu). Pliki flv lądują w audiorecorder/streams Red5. Żeby je odtwarzać za pomocą np. wspomnianego widżetu flowplayer musimy udostępnić katalog streams z poziomu serwera HTTP (dodanie go do document_root, alias pod jakiś URL). Najprostszy sposób "deweloperski" to stworzenie symlinka w site_media.
RkBlog

Django, 22 May 2011

Comment article
Comment article RkBlog main page Search RSS Contact