Использование Ajax для создания медиа-ресурсов (исходники)

Джэк Хэррингтон

Если спросить людей с улицы о том, какой сайт лучше всего олицетворяет новое поколение Web-приложений, то большинство из них ответят, что это YouTube. Этот сайт не только стал использовать новую технологию для привлечения пользователей, но также изменил сам принцип просмотра медиаинформации и наше к ней отношение. Наиболее интересные вещи иногда появляются на YouTube раньше, чем их можно будет посмотреть с помощью традиционных источников медиаинформации, а если этого не происходит, YouTube все равно превращается в один большой цифровой видеомагнитофон для всего мира.

Совместный доступ к медиа-информации изменяет мир, и при этом технологически реализовать его не так сложно. В этой статье я покажу, как применить Ajax на стороне клиента для создания Web-приложения, выполняющего функции простого видеохостинга.

Простой выбор видеоролика

Начнём с создания Web-сайта, содержащего список видеороликов, с помощью которого можно выбрать один из них для просмотра - сайта, который при смене просматриваемого ролика не потребует перезагрузки всей страницы. В листинге 1 приведён код такой страницы.

Листинг 1. index.html

                
<html>
<head>
<script src="prototype.js"></script>
</head>
<body>

<div id="movieHost">
</div>

<div id="movieList">
</div>

<script>
function setMovie( url )
{
  $('movieHost').innerHTML = '';
  var elEmbed = document.createElement( 'embed' );
  elEmbed.src = url;
  $('movieHost').appendChild( elEmbed );
}

new Ajax.Request( 'movies.xml', { 
  method: 'get',
  onSuccess: function( transport ) {
    var movieTags = transport.responseXML.getElementsByTagName( 'movie' );

    $('movieList').innerHTML = '';

    var bFirst = true;
    for( var b = 0; b < movieTags.length; b++ ) {
      var url = movieTags[b].getAttribute('url');
      var title = movieTags[b].getAttribute('title');
      if ( bFirst )
      {
        setMovie( url );
        bFirst = false;
      }
      var html = '<a href="javascript:void setMovie(\''+url+'\');">';
      html += title+'</a><br/>';
      $('movieList').innerHTML += html;
    }
  }
} );
</script>
</body>
</html>

Когда данные получены, с помощью метода getElementsByTagName() находим все теги <movie> и затем из каждого из них извлекаем заголовок ролика и его URL (атрибуты title и url). При этом если данный тег является первым в списке, то скрипт сразу же начинает проигрывать соответствующий ролик. В противном случае внутрь тега <div> с id="movieList" мы добавляем тег <a> (anchor-тег или «якорный» тег), щелчок по которому вызывает функцию setMovie(), запускающую соответствующий ролик для просмотра (Согласно приведённым здесь коду и рисунку для первого ролика также создаётся тэг <a>. [Прим. перев.]). Чтобы показать видео, мы просто очищаем содержимое тега <div> с id="movieHost", чтобы убрать предыдущий ролик, и затем создаем в нём тег <embed>, URL для которого берётся из списка.

Использование тега <embed> - это самый простой способ показать на странице видео, но он по-разному реализован в браузерах. Можно также использовать одновременно тег <object> и тег <embed>. (Ещё одной альтернативой является использование Macromedia Flash Player: чуть позже я немного скажу о нём в этой статье.)

В этом несложном примере movies.xml - это просто плоский файл (т.е. файл, состоящий из однородных записей), содержащий ссылки на короткие видеоролики, снятые мной. Он приведён в листинге 2.

Листинг 2. movies.xml

                
<movies>
  <movie url="spider.mov" title="Spider" />
  <movie url="swing.mov" title="Swing Set" />
  <movie url="water.mov" title="Water Splash" />
</movies>

Если открыть страницу в браузере, то можно увидеть что-то вроде рисунка 1.

Рисунок 1. Простая страница со списком видеороликов
Простая страница со списком видеороликов

Вверху страницы проигрывается ролик с помощью тега <embed>, а под ним находится список всех доступных для просмотра видеофайлов. При щелчке по любой из ссылок начинает проигрываться соответствующее видео.

Очевидно, эта система не очень хорошо приспособлена для создания больших видеоархивов, и необходимо реализовать какой-то поиск по списку видеороликов.

Список видеороликов с поиском

Чтобы сделать возможным поиск по списку, необходимо добавить немного кода. Усовершенствованный скрипт приведен в листинге 3. Здесь мы также добавили поле ввода для поиска (тег <input> id="q".

Листинг 3. Добавление возможности поиска

                
<html>
<head>
<script src="prototype.js"></script>
</head>
<body>

<table><tr><td valign="top">
  <input type="text" id="q" onkeyup="search()">
  <div id="movieList">
  </div>
</td><td valign="top">
  <div id="movieHost">
  </div>
</td>
</tr></table>

<script>
function setMovie( url )
{
  $('movieHost').innerHTML = '';
  var elEmbed = document.createElement( 'embed' );
  elEmbed.src = url;
  $('movieHost').appendChild( elEmbed );
}

function search()
{
  new Ajax.Request( 'search.php?q='+escape($('q').value), { 
    method: 'get',
    onSuccess: function( transport ) {
      var movieTags = transport.responseXML.getElementsByTagName( 'movie' );

      $('movieList').innerHTML = '';

      var bFirst = true;
      for( var b = 0; b < movieTags.length; b++ ) {
        var url = movieTags[b].getAttribute('url');
        var title = movieTags[b].getAttribute('title');
        if ( bFirst )
        {
          setMovie( url );
          bFirst = false;
        }
        var html = '<a href="javascript:void setMovie(\''+url+'\');">';
        html += title+'</a><br/>';
        $('movieList').innerHTML += html;
      }
    }
  } );
}
</script>
</body>
</html>

К событию, возникающему при отпускании кнопки клавиатуры, здесь привязан запуск метода search(). Этот метод аналогичен вызову Ajax.Request лишь с тем отличием, что сейчас он с помощью строки запроса обращается к странице search.php. Скрипт search.php возвращает данные в точно таком же XML-формате, какой имеет весь оригинальный список, а, значит код, осуществляющий синтаксический разбор XML-ответа, не требует изменений.

Конечно, запуск функции search() при отпускании кнопки клавиатуры делает приложение слишком чувствительным. В идеале система должна ждать около секунды, прежде чем начинать поиск, чтобы можно было успеть полностью ввести текст для поиска, избежав при этом мерцания списка. Такое поведение можно легко реализовать с помощью метода window.setTimeout().

Листинг 4 содержит изменённый код скрипта search.php.

Листинг 4. search.php

                
<?php
header( 'content-type: text/xml' );

$movies = array();
$movies['spider.mov'] = 'Spider';
$movies['swing.mov'] = 'Swing Set';
$movies['water.mov'] = 'Water Splash';
?>
<movies>
<?php
foreach( $movies as $k => $v ) {
if ( strlen( $_GET['q'] ) > 0 &&
  preg_match( '/'.$_GET['q'].'/i', $v ) ) {
?>
<movie url="<?php echo($k) ?>" title="<?php echo($v) ?>" />
<?php
} }
?>
</movies>

В начале скрипта мы создаём массив, содержащий все видеоролики. В целях простоты примера данные здесь жёстко прописаны. В реальности эти элементы скорее всего будут извлекаться из базы данных, содержащей списки видео файлов.

Далее к каждому заголовку ролика из списка применяется регулярное выражение поискового запроса, и если оно подходит, то выводится тег <movie> с соответствующими URL и названием.

Если теперь открыть страницу и ввести букву s, то мы увидим страницу, показанную на рисунке 2.

Рисунок 2. Страница, на которой можно искать видеоролики, и простой запрос
Страница, на которой можно искать видеоролики, и простой запрос

А если нажать Delete и ввести "water", то мы увидим страницу, показанную на рисунке 3.

Рисунок 3. Поиск видеоролика с заголовком, содержащим слово water
Поиск видеоролика с заголовком, содержащим слово water

Хотя основная цель этой статьи - показать, как можно создать клиентскую часть приложения, используя динамический HTML (DHTML) и Ajax, существует ещё много вещей, которые нужно знать, чтобы создать сайт с совместно используемыми видеоданными.

Основы работы с совместно используемыми видеоданными

Переходя на несколько минут от практики к некоторым теоретическим вопросам, позвольте мне рассказать о некоторых более сложных аспектах работы с совместно используемыми видеоданными. Рассмотрим три основных вопроса:

  • Как хранить и выдавать в потоковом режиме видеоданные
  • Как работать с различными видеоформатами
  • Как извлечь отдельные кадры для предварительного просмотра (thumbnail'ы) и другую информацию из закаченных видеофайлов

Хранение видеоданных является довольно сложной задачей - особенно для небольших приложений. Видеофайлы имеют большой объём, и поэтому для их хранения требуется дорогое аппаратное обеспечение. Дополнительные расходы связаны с необходимостью обеспечения широкополосного канала для предоставления пользователям доступа к этим данным. Вы могли бы купить своё собственное оборудование и использовать его для организации такого хостинга. Можно также воспользоваться каким-нибудь сервисом наподобие S3 от Amazon, который позволяет закачивать на сервер любые данные (резервные базы данных, изображения, видеоролики, и т.п.) и транслировать их из вычислительного центра Amazon за разумную цену. Вероятно, было бы полезным изучить какой-нибудь из этих сервисов, прежде чем начинать финансирование собственного вычислительного центра.

Следующий вопрос - видеоформаты - представляет собой интересную и достаточно сложную задачу. Существует множество видеоформатов, и не все проигрыватели могут работать со всеми форматами. На самом деле большинство проигрывателей обрабатывают только один предпочитаемый ими формат. Пожалуй здесь самым лучшим решением, позволяющим облегчить пользователю процесс закачки файлов, является выбор какого-то одного конкретного формата и последующее преобразование всех входящих видеофайлов в этот формат. Есть очень удобное средство для выполнения этих операций - это программа FFmpeg , работающая из командной строки. С помощью неё можно не только конвертировать форматы, но и извлекать отдельные кадры из видеороликов и таким образом создавать небольшие картинки для предварительного просмотра (thumbnail’ы).

Вопрос выбора определённого формата может быть довольно сложным. В настоящее время бесспорным лидером здесь является Flash-видео, однако постепенно набирает популярность и Windows Media®-формат, особенно с выходом релиза Microsoft Silverlight (ранее известного как WPF/Everywhere). FFmpeg может преобразовывать практически любые типы видеороликов в формат Flash-видео. Существуют также несколько бесплатных Flash-проигрывателей с открытыми исходными кодами, которые можно легко встроить в свой сайт. Комбинируя эти проигрыватели со скриптами, рассмотренными выше, можно создать комплексное решение для ресурса совместно используемых видеоданных с применением технологии Ajax на стороне клиента.

Но видео - это не единственное, чем живёт Сеть: предоставление общего доступа к картинкам также является важным аспектом развития Web.

Слайдшоу

В листинге 5 приведён код простого слайдшоу на DHTML, получающий данные из XML-файла.

Листинг 5. index.html

                
<html>
<head>
<script src="prototype.js"></script>
</head>
<body bgcolor="black">
<div style="text-align:center;">
<img id="imgItem" src="" style="display:none;"><br>
<div id="imgTitle" style="color:white;font-family:arial;font-size:24pt;">
</div>
</div>
<script>
var g_images = [];
var g_slideIndex = 0;

function showSlide()
{
  $('imgTitle').hide();
  $('imgItem').hide();

  var height = 600;
  var width = ( height / g_images[ g_slideIndex ].height ) * 
    g_images[ g_slideIndex ].width;

  $('imgItem').src = g_images[ g_slideIndex ].src;
  $('imgItem').width = width;
  $('imgItem').height = height;

  $('imgTitle').innerHTML = g_images[ g_slideIndex ].title;

  $('imgTitle').show();
  $('imgItem').show();

  g_slideIndex++;
  if ( g_slideIndex >= g_images.length )
    g_slideIndex = 0;
}

new Ajax.Request( 'images.xml', { 
  method: 'get',
  onSuccess: function( transport ) {
    var imageTags = transport.responseXML.getElementsByTagName( 'image' );

    for( var b = 0; b < imageTags.length; b++ ) {
      g_images.push( {
        src: imageTags[b].getAttribute('src'),
        title: imageTags[b].getAttribute('title'),
        width: imageTags[b].getAttribute('width'),
        height: imageTags[b].getAttribute('height')
      } );
    }

    showSlide();

    window.setInterval( showSlide, 5000 );
  }
} );
</script>
</body>
</html>

Код построен на JavaScript-библиотеке Prototype.js. Для получения списка изображений, которые требуется показать, здесь также используется объект Ajax.Request. Возвращённые в результате такого запроса XML-данные подвергаются далее синтаксическому разбору для извлечения URL каждого изображения, а также его ширины, высоты и заголовка. Функция showSlide() осуществляет собственно показ слайда. Таймер запускает её каждые 5 секунд для смены картинки.

Слайд отображается с помощью одного тега <image> для текущей картинки и одного тега <div> - для заголовка. Сам процесс слайдшоу происходит так: сначала мы просто скрываем текущую картинку и заголовок, затем изменяем адрес изображения (атрибут "src") и текст и, наконец, снова делаем их видимыми. Если вы захотите добавить эффекты плавного появления и плавного исчезновения, то я рекомендовал бы вам воспользоваться классом Effects библиотеки Scriptaculous, которая также построена на Prototype.js.

В листинге 6 показано содержимое файла данных об изображениях.

Листинг 6. images.xml

                
<images>
 <image src="images/megan1_875_700.jpg" title="Megan" width="875" height="700" />
 <image src="images/oso1_875_700.jpg" title="Oso 1" width="875" height="700" />
 <image src="images/oso2_873_700.jpg" title="Oso 2" width="873" height="700" />
</images>

Здесь данные также жёстко прописаны, но их можно легко сгенерировать и с помощью PHP-скрипта. Слайдшоу в действии показано на рисунке 4.

Рисунок 4. Простое слайдшоу
Простое слайдшоу

Примечение: ранее я публиковал значительно более хитрую реализацию слайдшоу. Этот пример отличается тем, что здесь используется библиотека Prototype.js и смена слайда осуществляется гораздо проще.

Заключение

Сайты, подобные Flikr и YouTube, являются лишь верхушкой тех потенциальных возможностей, которыми обладают медиа-данные в Web. В этой статье были описаны несколько простых способов показа видео и изображений, и вы можете использовать их в своих проектах. Если эти приёмы у вас работают, пожалуйста, дайте мне знать об этом - присоединяйтесь к обсуждению на форуме Ajax на developerWorks и расскажите о своих результатах.


Страница сайта http://185.71.96.61
Оригинал находится по адресу http://185.71.96.61/home.asp?artId=9873