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):ant dist
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))
@login_required
@csrf_exempt
def save_to_db(request):
"""
recording save action called by the flash applet
"""
print request.POST
return HttpResponse('ok')

Comment article