Недавно на Хабре была статья о том, как у парня отобрали домен, с миллионной посещаемостью, и как он с этим боролся. Из чистого интереса я зашел поглядеть, что же там такое, и обнаружил ну очень удобный плеер. Он понравился и мне, и моим друзьям, и почти сразу стал основным средством для прослушивания музыки.
Некоторое время спустя, один из моих друзей принес мне Nexus 7, и попросил установить на него Ubuntu Linux. Просьба была выполнена, система более-менее настроена, и все было хорошо, пока не выяснилось, что плеер не работает. Стоит уточнить, что используется Chromium Browser 28, и HTML5 он поддерживает.
На одном сайте я нешел простой тест, который позволяет определить какие типы аудиофайлов умеет декодировать браузер. Оказалось, что mp3 все таки не проигрывается. Причиной тому является то, что по умолчанию с Chromium ом устанавливается пакет chromium-ffmpeg-codecs, в который не входит кодек для mp3. Кодек для mp3 входит в пакет chromium-ffmpeg-codecs-nonfree, но для ARM такого пакета не оказалось. Я решил, что если браузер не может декодировать mp3, но может декодировать другие форматы, wav, например, то нужно перед проигрыванием перекодировать mp3 в wav.
Немножечко поковырявшись в коде плеера, выяснилось, что для проигрывания музыки используется SoundManager2, ссылка на mp3 файл ему передается через переменную url в функции createSm2Sound, в файле nano.js.
Решение было принято следующее — пропатчить nano.js таким образом, чтобы через переменную url передавался адресс, при обращении к которому mp3 файл бы конвертировался в wav, и он уже передавался плееру. Для этого у нас на на планшете будет работать mongoose (очень маленький, быстрый, удобный, кросплатформенный web-server) с CGI скриптом, написаном на bash, который при обращении конвертирует mp3 (ссылка на него передается скрипту GET запросом) в wav, и “отдает” его браузеру. Так же на этом сервере будет хоститься патченный nano.js.
Итак, приступим. Для начала нужно скачать исходник и собрать веб-сервер.
wget https://mongoose.googlecode.com/files/
tar xvf mongoose-3.8.tgz
cd mongoose
make linux
После этого в текущей папке появится бинарник mongoose. Скопируем его для удобства в /usr/bin/
sudo cp mongoose /usr/bin/
Веб сервер скомпилирован и “установлен”, в обход пакетного менеджера, но это не страшно :).
Далее, необходимо написать CGI скрипт, он совсем простой. Я использую ffmpeg, но можно использовать любой другой конвертер, например mencoder.
#!/bin/bash
DIRECTORY=$(cd `dirname $0` && pwd)
ffmpeg -y -i ${QUERY_STRING:0:$((${#QUERY_STRING}-4))} $DIRECTORY/temp.wav
echo "Connection:keep-alive"
echo "Content-Type: audio/wav"
echo "Content-Length: $(du -b $DIRECTORY/temp.wav | awk '{print $1}')"
echo ""
cat $DIRECTORY/temp.wav
Скрипт должен иметь права на исполнение. Добавить их можно так:
chmod +x convert.sh
Хотелось бы обратить внимание на страшную конструкцию ${QUERY_STRING:0:$((${#QUERY_STRING}-4))}, она отрезает 4 последних символа от строки в переменной QUERY_STRING. Значение этой переменной определяется содержимым строки запроса после знака ?, и в нашем случае, имеет вид *сылка на mp3 файл*+”.wav”. Если не добавить расширение .wav, SoundManager не захочет это проигрывать, я не вникал почему так, но очевидно, что там какая-то привязка именно к расширению файла. Таким образом, что бы получить ссылку на mp3 файл, от QUERY_STRING необходимо отрезать 4 последних символа (“.wav”). После того, как файл конвертирован, скрипт формирует HTTP заголовок и отдает содержимое wav файла.
Далее нам необходимо пропатчить nano.js. Как я уже говорил, ссылка на mp3 файл передается через переменную url, и изначально имела вид:
var url = li.attr('url');
После патча:
var url = “http://localhost:9090/convert.sh?”+li.attr('url')+”.wav”;
Теперь необходимо сделать так, чтобы вместо оригинального nano.js загружался наш патченый nano.js, для этого я воспользовался одним простым, но полезным дополнением для хромиума. После того как дополнение установлено, необходимо создать правило, что куда перенаправлять:
http://pleer.com/js/nano.js > http://localhost:9090/nano.js
Осталось только “поднять” наш веб сервер, и все должно работать.
mongoose -listening_ports 9090 -cgi_pattern **.sh$ -document_root .
После опции -document_root, если при запуске сервера вы не находитесь в папке с convert.sh и node.js, необходимо указать путь до папки с данными файлами.
Хотелось бы заметить, что как бы страшно это не выглядело, во-первых, это лучше чем ничего, а во-вторых, конвертирование происходить не столь долго, от 3-10 секунд. Спасибо за внимание.
Автор: ParkeTg