Feb 25th, 2007
Windows Media Player и управление фоновой музыкой
Недавно нам поставили задачу сделать на сайте фоновую музыку, которая бы не прерывалась при переходе между страницами. Задача осложнялась ещё и тем, что владелец сайта должен был иметь возможность периодически обновлять треки на сервере. Идею с использованием фреймов откинули сразу. Сошлись на том, что достаточно будет запоминать позицию и при переходе на следующую страницу воспроизводить трек с того же места.
Сначала начали обсуждать, каким образом реализовать всё это на флеше, как запоминать и передавать позицию, сделать пред-загрузку, корректное кеширование, чтоб музыка моментально начинала играть, чтоб всё это дело не гоняло трафик посетителя. Для упрощения экспорта и обеспечения непрерывного воспроизведения хотели сделать, чтоб один флеш во время проигрывания подтягивал другой и запускал его…
И тут кто-то из нас вспомнил, что недавно мы делали систему “web-tv” и использовали там Windows Media Player. Вот оно! Он же всё это уже умеет. И подгружает во время проигрывания, и кеширует, и playlist на xml сгенерировать можно. Поэксперементировали с wma-экспортёром, сошлись на оптимальных параметрах размер-качество 32kbs, 44kHz, mono. На компьютерных колонках потери качества не слышно, да и для буржуев 1Mb (за 5 мин) - это ерунда. И интеграция много не занимает, просто вставляем на страницу следующий код, вуаля, музыка играет!
<object id="MediaPlayer1" width="0" height="0"
classid="CLSID:22D6F312-B0F6-11D0-94AB-0080C74C7E95"
type="application/x-oleobject">
<param name="URL" value="test.wma" />
<param name="ShowControls" value="0" />
<param name="AutoStart" value="true" />
<param name="EnableContextMenu" value="false" />
<param name="stretchToFit" value="true" />
<param name="CurrentPosition" value="<позиция>" />
<param name="uiMode" value="none" />
<embed
src="test.wma"
height="0" width="0"
autoStart="true"
CurrentPosition="<позиция>"
DisplaySize="4"
uiMode="none"
StretchToFit="1"
border="0"
type="application/x-mplayer2"
></embed>
</object>
Но, как оказалось, для полного счастья нужно не только научится получать от объекта текущую позицию трека для запоминания в кукисах. Правила usability гласят, что наличие фоновой музыки на сайте обязательно должно сопровождатся возможностью её выключить (т.е. кнопкой Stop/Play). А так как мы прячем видимую часть WMP, для реализации необходима возможность управления воспроизведением из клиентского скрипта.
Покопавшись немного в MSDN и нарыв в интернете статей с примерами я нашёл, что начиная с версии 7.0 управление WMP осуществляется через специальный объект “Controls”, который имеет весь необходимый для поставленной задачи интерфейс, а именно методы Play(), Stop(), Pause() и свойство CurrentPosition. Полный список параметров, версий WMP и значений classid для них можно посмотреть здесь. Для того, чтобы использовать Controls в клиентском скрипте нужно разрешить его создание в теге <object> (параметр EnablePositionControls) и заменить classid на нужную версию. Теперь наш код выглядел так:
<object id="MediaPlayer1" width="0" height="0"
classid="CLSID:6BF52A52-394A-11D3-B153-00C04F79FAA6"
type="application/x-oleobject">
<param name="URL" value="test.wma" />
<param name="ShowControls" value="0" />
<param name="AutoStart" value="false" />
<param name="EnableContextMenu" value="false" />
<param name="EnablePositionControls" value="true" />
<param name="stretchToFit" value="false" />
<param name="CurrentPosition" value="<позиция>" />
<param name="PlayCount" value="100" />
<param name="uiMode" value="none" />
<embed
src="test.wma"
height="0" width="0"
autostart="0"
currentposition="<позиция>"
playcount="100"
uimode="none"
stretchtofit="0"
border="0"
type="application/x-mplayer2"
></embed>
</object>
Осталось только периодически запоминать позицию трека из MediaPlayer1.contrlos.CurrentPosition используя setTimeout, да и кнопку Play/Stop сделать тоже не составило труда.
Вроде готово, работает, запоминает позицию при переходе по страницам, останавливает, играет дальше при нажатии кнопки. Однако после контрольного теста в Firefox выяснилось, что ничего не работает, а в консоли слошные JavaScript Error-ы! В дебаге я обнаружил, что в Firefox объект плеера не имеет ни свойства controls, ни какого-либо другого позволяющего определить даже текущую позицию трека
. Посетив офсайт выяснилось, что за объект WMP у браузеров мозиллы отвечает специальный плагин, который действительно не поддерживает Controls, и что Firefox вобще не умеет (и не извесно когда научится) управлять воспроизведением.
Но задача то поставлена и уже наполовину сделана! Поковыряв ещё пол часа я всё же нашёл выход, как говорят в народе “через ж..”. А идея пришла во время поиска controls у Firefox-плагина. Так как выводить его многочисленные свойства методом alert() было не удобно, я воспользовался выводом через innerHTML. Вот решение! Так как свойство innerHTML поддерживается всеми современными браузерами, то заключив тег-object внутрь тега-div получаем универсальную возможность управлять Microsoft-овским плеером в любом браузере. Для этого нужно создать шаблон тега-object, подставить в него нужные значения (позицию, состояние, имя файла и т.п.) и проинициализировать innerHTML тега-div. В результате, при замене, создаётся новый объект WMP в необходимом состоянии. К сожалению, узнать текущую позицию трека таким способом всёравно не получится. Но её можно вычислить вручную. Осталось только оформить всё это в виде небольшой .js библиотеки и задача решена. Таким образом исходный html-код может изначально вообще не содержать тега-object, а создавать его можно уже клиентским скриптом после полной загрузки страницы.
В своём проекте я скомбинировал оба вышеперечисленных способа, первый для IE , второй - для остальных. Ещё один совет, второй метод актуален для валидности кода, так как w3c ругается на тег <embed>. Я так и не нашёл способа добавления WMP в Firefox без использования этого тега.
Сильно!
Ну и требования у заказчиков…
Недавно была подобная задача: необходимо было реализовать проигрывание звуковых файлов в IE, Firefox и Safari на маках. Решил таким же мега универсальным методом!
Очень интересуюсь этим направлением, только для видео.
Под ИЕ все работает без проблем.
А вот …
Как считать currentposition под FF, Opera и т.д.
alert(Player.currentposition);
не работает
Если можно чуть подробнее этот момент!
Я ж написал, нету у FF-плагина ни свойства controls, ни currentposition.
Чтобы всё работало, нужно самому считать текущую позицию, т.е. запускать счётчик при старте, останавливать при паузе, обнулять при стопе… Для этого нужно передать в страницу, или ajax-ом получить длину трека в секундах.
Это всё не так уж и сложно, можно небольшую js-библиотечку сделать и использовать. Я делал, но не доделал, поэтому не буду выкладывать.
Mne eto k sogeleniu ne podhodit potomu chto user moget pereyti po klipu polzunkom i poteryaetsya :((
Да, абсолютно верно, панель управления воспроизведением при таком подходе нужно реализовывать самому. А по-другому никак.
Я так и не понял, как же сделать обращение к свойству controls для FF?
Хотя бы controls.play() и controls.stop().
господа,
Действительно, как же сделать обращение к методам объекта типа play, stop etc из FF, Opera?
Не совсем понятно, как это было сделано у автора?
Можно ли привети пример?
Заранее спасибо!
Бьюсь об заклад, что в самом WM-плеере есть функции, заменяющие вторую часть (тег ). Просто это 2-а разных способа подгружать музыку, и соединять их не совсем нужно… Или так, или так. А совместное их использование только затруднит решение проблемы о совместимости в разных браузерах. А еще, у Firefox, на этот счет, не поддерживается команда controls, но на 100 пудов уверен, что можно найти функции этой команды, но под другим именем, как и вообще при программировании под Firefox!
Alex_R, Смотри тут http://trioconsultinginc.com/, но он недоделаный. Счётчик не работает и нет блокировки нескольких открытых страниц.
Ker-Tinor, Перебирал и просматривал все свойства объекта в FF, ничего подобного там нет.