Пример видеоданных: Video Jukebox

Flash Player 9 и более поздних версий, Adobe AIR 1.0 и более поздних версий

Следующий пример создает простой видеоавтомат (Video Jukebox), который динамически загружает список видеофайлов для воспроизведения в последовательном порядке. Так можно создать приложение, которое дает пользователю возможность просмотреть серию учебных видеоматериалов или указывает, какие рекламные ролики нужно показать перед воспроизведением видеофайла, запрашиваемого пользователем. В этом примере используются следующие функции ActionScript 3.0:

  • обновление точки воспроизведения на основе прогресса воспроизведения видеофайла;

  • прослушивание и анализ метаданных видеофайла;

  • обработка определенных кодов в сетевом потоке;

  • загрузка, воспроизведение, приостановка и остановка динамического загруженного FLV-файла;

  • изменение размеров объекта Video в списке отображения на основе метаданных сетевого потока.

Получить файлы приложения для этого примера можно на странице www.adobe.com/go/learn_programmingAS3samples_flash_ru . Файлы приложения VideoJukebox находятся в папке Samples/VideoJukebox. Приложение состоит из следующих файлов.

File

Описание

VideoJukebox.fla

или

VideoJukebox.mxml

Основной файл приложения для Flex (MXML) или Flash (FLA).

VideoJukebox.as

Класс, обеспечивающий основную функциональность приложения.

playlist.xml

Файл, в котором перечислены видеофайлы, предназначенные для загрузки в видеоавтомат.

Загрузка внешнего файла со списком видеофайлов для воспроизведения

Внешний файл playlist.xml указывает, какие видеофайлы необходимо загрузить и в каком порядке их нужно воспроизводить. Для загрузки XML-файла необходимо использовать объекты URLLoader и URLRequest, как показано в следующем коде.

uldr = new URLLoader(); 
uldr.addEventListener(Event.COMPLETE, xmlCompleteHandler); 
uldr.load(new URLRequest(PLAYLIST_XML_URL));

Этот код помещается в конструктор класса VideoJukebox, поэтому файл загружается перед выполнением основной части кода. Сразу после завершения загрузки XML-файла вызывается метод xmlCompleteHandler() , который преобразует внешний файл в объект XML, как показано в следующем коде.

private function xmlCompleteHandler(event:Event):void 
{ 
    playlist = XML(event.target.data); 
    videosXML = playlist.video; 
    main(); 
}

Объект XML с именем playlist содержит необработанные данные в формате XML из внешнего файла, в то время как XML видео является объектом XMLList, который содержит только видеоузлы. Пример файла playlist.xml можно найти в следующем коде.

<videos> 
    <video url="video/caption_video.flv" /> 
    <video url="video/cuepoints.flv" /> 
    <video url="video/water.flv" /> 
</videos>

В завершение, метод xmlCompleteHandler() вызывает функцию main() , которая создает экземпляры различных компонентов в списке отображения, а также объекты NetConnection и NetStream, используемые для загрузки внешних FLV-файлов.

Создание пользовательского интерфейса

Для создания пользовательского интерфейса необходимо перетащить пять экземпляров Button в список отображения, присвоив им следующие имена: playButton , pauseButton , stopButton , backButton и forwardButton .

Для каждого экземпляра Button необходимо назначить обработчик события click , как показано в следующем коде.

playButton.addEventListener(MouseEvent.CLICK, buttonClickHandler); 
pauseButton.addEventListener(MouseEvent.CLICK, buttonClickHandler); 
stopButton.addEventListener(MouseEvent.CLICK, buttonClickHandler); 
backButton.addEventListener(MouseEvent.CLICK, buttonClickHandler); 
forwardButton.addEventListener(MouseEvent.CLICK, buttonClickHandler);

Метод buttonClickHandler() использует инструкцию switch, чтобы определить, какой экземпляр Button, получил щелчок мыши, как показано в следующем коде.

private function buttonClickHandler(event:MouseEvent):void 
{ 
    switch (event.currentTarget) 
    { 
        case playButton: 
            ns.resume(); 
            break; 
        case pauseButton: 
            ns.togglePause(); 
            break; 
        case stopButton: 
            ns.pause(); 
            ns.seek(0); 
            break; 
        case backButton: 
            playPreviousVideo(); 
            break; 
        case forwardButton: 
            playNextVideo(); 
            break; 
    } 
}

Затем добавьте в список отображения объект Slider и присвойте ему имя экземпляра volumeSlider . Следующий код задает свойству liveDragging экземпляра Slider значение true и определяет прослушиватель для события change .

volumeSlider.value = volumeTransform.volume; 
volumeSlider.minimum = 0; 
volumeSlider.maximum = 1; 
volumeSlider.snapInterval = 0.1; 
volumeSlider.tickInterval = volumeSlider.snapInterval; 
volumeSlider.liveDragging = true; 
volumeSlider.addEventListener(SliderEvent.CHANGE, volumeChangeHandler);

Добавьте в список отображения объект ProgressBar и присвойте ему имя экземпляра positionBar . Задайте его свойству mode значение manual (вручную), как показано в следующем коде.

positionBar.mode = ProgressBarMode.MANUAL;

В завершение, добавьте в список отображения объект Label и присвойте ему имя экземпляра positionLabel . Значение этого экземпляра Label будет задаваться экземпляром Timer.

Прослушивание метаданных объекта Video

Когда проигрыватель Flash Player находит метаданные для каждого загруженного видеофайла, вызывается обработчик обратного вызова onMetaData() для свойства client объекта NetStream. Следующий код создает экземпляр Object и определяет указанный метод обратного вызова.

client = new Object(); 
client.onMetaData = metadataHandler;

Метод metadataHandler() копирует свои данные в свойство meta, ранее определенное в коде. Это позволяет получать метаданные для текущего видео в любой момент в рамках всего приложения. Затем размер объекта Video в рабочей области изменяется в соответствии с шириной и высотой, указанными в метаданных. В завершение, выполняется перемещение и изменение размера экземпляра ProgressBar с именем positionBar в соответствии с размером текущего воспроизводимого видео. Ниже приводится полный код метода metadataHandler() .

private function metadataHandler(metadataObj:Object):void 
{ 
    meta = metadataObj; 
    vid.width = meta.width; 
    vid.height = meta.height; 
    positionBar.move(vid.x, vid.y + vid.height); 
    positionBar.width = vid.width; 
}

Динамическая загрузка видеоданных

Для динамической загрузки каждого видеофайла приложение использует объекты NetConnection и NetStream. Следующий код создает объект NetConnection и передает значение null методу connect() . Указав значение null , Flash Player подключается к видеофайлу на локальном сервере, а не на удаленном, таком как Flash Media Server.

Следующий код создает экземпляры NetConnection и NetStream, определяет прослушиватель для события netStatus и назначает экземпляр Object с именем client свойству client .

nc = new NetConnection(); 
nc.connect(null); 
 
ns = new NetStream(nc); 
ns.addEventListener(NetStatusEvent.NET_STATUS, netStatusHandler); 
ns.client = client;

Метод netStatusHandler() вызывается каждый раз, когда изменяется состояние видео, в том числе при запуске, остановке или буферизации воспроизведения, а также когда не удается найти видеопоток. В следующем коде представлен обработчик событий netStatusHandler() .

private function netStatusHandler(event:NetStatusEvent):void 
{ 
    try 
    { 
        switch (event.info.code) 
        { 
            case "NetStream.Play.Start": 
                t.start(); 
                break; 
            case "NetStream.Play.StreamNotFound": 
            case "NetStream.Play.Stop": 
                t.stop(); 
                playNextVideo(); 
                break; 
        } 
    }  
    catch (error:TypeError)  
    { 
        // Ignore any errors. 
    } 
}

Предыдущий пример оценивает свойство code объекта info и отфильтровывает коды «NetStream.Play.Start», «NetStream.Play.StreamNotFound» или «NetStream.Play.Stop». Остальные коды игнорируются Если запускается сетевой поток, код запускает экземпляр Timer, который обновляет точку воспроизведения. Если сетевой поток не удается обнаружить или он остановлен, экземпляр Timer останавливается и приложение пытается воспроизвести следующий видеофайл в списке воспроизведения.

Каждый раз при выполнении экземпляра Timer экземпляр ProgressBar с именем positionBar обновляет текущую позицию, вызывая метод setProgress() класса ProgressBar, также обновляется экземпляр Label с именем positionLabel , отражая прошедшее время и общее время для текущего видеофайла.

private function timerHandler(event:TimerEvent):void 
{ 
    try 
    { 
        positionBar.setProgress(ns.time, meta.duration); 
        positionLabel.text = ns.time.toFixed(1) + " of " meta.duration.toFixed(1) + " seconds"; 
    }  
    catch (error:Error) 
    { 
        // Ignore this error. 
    } 
}

Управление громкостью видео

Управлять громкостью динамически загружаемого видеофайла можно с помощью свойства soundTransform объекта NetStream. Приложение VideoJukebox позволяет изменять уровень громкости путем изменения значения экземпляра Slider с именем volumeSlider . Следующий код демонстрирует изменение громкости путем присвоения значения компонента Slider объекту SoundTransform, который затем передается свойству soundTransform объекта NetStream.

private function volumeChangeHandler(event:SliderEvent):void 
{ 
    volumeTransform.volume = event.value; 
    ns.soundTransform = volumeTransform; 
}

Управление воспроизведением видео

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

Следующий метод получает URL-адрес видеофайла из объекта XMLList для выделенного в данный момент индекса.

private function getVideo():String 
{ 
    return videosXML[idx].@url; 
}

Метод playVideo() вызывает метод play() объекта NetStream, чтобы загрузить выделенный в данный момент видеофайл.

private function playVideo():void 
{ 
    var url:String = getVideo(); 
    ns.play(url); 
}

Метод playPreviousVideo() уменьшает текущий индекс видеофайла, вызывает метод playVideo() для загрузки нового видеофайла и отображает строку прогресса.

private function playPreviousVideo():void 
{ 
    if (idx > 0) 
    { 
        idx--; 
        playVideo(); 
        positionBar.visible = true; 
    } 
}

Последний метод, playNextVideo() , увеличивает индекс видео и вызывает метод playVideo() . Если текущий видеофайл является последним в списке воспроизведения, вызывается метод clear() для объекта Video, а свойству visible экземпляра ProgressBar задается значение false .

private function playNextVideo():void 
{ 
    if (idx < (videosXML.length() - 1)) 
    { 
        idx++; 
        playVideo(); 
        positionBar.visible = true; 
    } 
    else 
    { 
        idx++; 
        vid.clear(); 
        positionBar.visible = false; 
    } 
}