Программа Flash работает со следующими форматами файлов:
Существует два способа использования видео:
Важно, что частота кадров фильма может быть любая, она никак не зависит от частоты кадров Flash-фильма.
Однако «добраться» до временной шкалы загружаемых FLV-файлов не удается (отдельные кадры недоступны), добавить новые интерактивные элементы на другие слои также нельзя не будет синхронизации. Фильмом с постепенной загрузкой невозможно управлять из своей программы, для этого используется специальный проигрыватель компонент FLVPlayback.
В этом разделе мы построим ролик, который позволяет полностью управлять проигрыванием загруженного фильма. Его внешний вид показан на рисунке ниже (ролик не действует, это сделано для сокращения объема учебника).
Откройте файл PRACTICE\12\player.fla. Создайте слой Видео и выберите пункт меню FileImportImport video. |
В окне Select Video щелкните по кнопке Browse (Обзор) и выберите файл osob.mpg и перейдите к следующему окну (кнопка Next внизу). |
В окне Deployment выберите вариант Embed video in SWF and play in timeline (внедрить видео в SWF-файл и проигрывать на временной шкале). В остальных окнах мастера оставьте все параметры без изменений. |
Когда импорт видео завершится, в библиотеке вы обнаружите новый символ osob.mpg типа Embedded Video (внедренное видео). Его копия будет на сцене.
Выделите на сцене видео фильм и установите на панели Properties координаты X=0 и Y=0. Просмотрите фильм. |
Перейдите к последнему кадру видео (это кадр 204) и вставьте там промежуточные кадры в слоях Фон и Кнопки. |
Создайте новый слой Программа, перейдите к кадру 1 и добавьте к нему команду stop();.
Выделите кнопку
и присоедините к ней код
on (release) { if ( playing ) _root.stop(); else _root.play(); } |
Выделите кнопку
и добавьте к ней обработчик
on (release){ playBtn.gotoAndStop(1); gotoAndStop(1); } |
Если фильм сейчас проигрывается (playBtn.playing=true), после перехода надо продолжить проигрывание, то есть использовать переход gotoAndPlay. Если фильм остановлен, применяется метод gotoAndStop.
Выделите кнопку
и добавьте к ней обработчик
on (release){ frame = Math.max(1,_currentframe-10); if ( playBtn.playing ) gotoAndPlay(frame); else gotoAndStop(frame); }Аналогичный обработчик добавьте к кнопке (быстрая перемотка вперед). |
С помощью этой кнопки будем не вообще останавливать звук, а заглушать его, устанавливая нулевую громкость с помощью метода setVolume объекта Sound. При создании этого объекта нужно взять звук с главного монтажного стола _root.
Добавьте обработчик события release для кнопки
:
on (release) { snd = new Sound(_root); if ( ! mute ) snd.setVolume(0); else snd.setVolume(100); }Проверьте работу всех кнопок. |
Клип Индикатор построен так, что при перетаскивании он вызывает функцию _root.setFraction, передавая ей в параметре frac значение смещения от 0 до 1. Легко проверить, что нужный номер кадра вычисляется как 1+frac*(_totalframes-1), а для округления к ближайшему целому значению нужно использовать метод round.
Добавьте к кадру 1 код функции function setFraction ( frac ) { frame = Math.round(1+frac*(_totalframes-1)); if ( playBtn.playing ) gotoAndPlay(frame); else gotoAndStop(frame); } |
part = (_root._currentframe-1) / (_root._totalframes-1);Вызов этой функции мы добавляем в обработчик enterFrame клипа.
Выделите линию-индикатор и добавьте к ней обработчик события enterFrame;
onClipEvent (enterFrame) { part = (_root._currentframe-1) / (_root._totalframes-1); setFraction ( part ); }Проверьте окончательный вариант и сохраните файл. |
Запустите фильм, в окне проигрывателя выберите пункт меню ViewDownload Setting56K (модем 56 Кбит/с) и затем ViewBandwidth Profiler. |
Серые столбики показывают объем каждого кадра, красная линия пропускную способность канала связи (400 байт на кадр).
Чтобы посмотреть процесс загрузки на заданной скорости, выберите пункт меню ViewSimulate Download. |
Используя потоковую (постепенную) загрузку, о которой мы поговорим далее, в принципе можно не дожидаться окончания загрузки всего фильма. Однако каждый кадр занимает более 400 байт, поэтому даже при потоковой загрузке посмотреть фильм в реальном времени не удается. По-настоящему нормальный просмотр без задержек возможен, если в меню ViewDownload Setting выбрать выделенную линию T1 (131 Кбит/с).
Мы вернемся к примеру телевизора с пультом, который был разобран в прошлой теме, только теперь будем использовать видеофильмы для каждого канала (рисунок ниже картинка, кнопки не работают).
В отличие от предыдущего примера, мы не будем сразу выводить клипы на сцену, а сделаем это во время выполнения из программы.
Откройте файл PRACTICE\12\tv.fla. Войдите в меню FileImportImport video, щелкните по кнопке Browse и выберите файл channels.mov. Перейдите к следующему окну мастера. |
В окне Deployment выберите вариант Embed video in SWF and play in timeline (внедрить видео в SWF-файл и проигрывать на временной шкале). |
В следующем окне Embedding в списке Symbol type выберите вариант Movie Clip, сбросьте флажок Place instance on stage (разместить клипы на сцене) и щелкните по строчке Edit the video first (сначала редактировать видео). |
Выбор варианта Edit the video first говорит о том, что мы хотим редактировать видео. В этом файле записаны подряд отрывки передач трех каналов, нам придется разрезать его на три небольших клипа в следующем окне мастера, которое называется Split Video (разделить видео).
В правой части вы видите сам ролик, движок над линейкой показывает текущий кадр, он перемещается мышкой. Синяя область на линейке это выделенный фрагмент. Его границы определяются треугольниками под линейкой, которые также можно перетаскивать мышью.
Кнопка Preview Clip позволяет просмотреть только выделенный фрагмент. Слева от нее находится блок управления, содержащий кнопки:
начать проигрывание с текущего кадра; | |
остановить проигрывание; | |
установить левую границу клипа на текущий кадр; | |
установить правую границу клипа на текущий кадр; | |
перейти на 1 кадр назад; | |
перейти на 2 кадр вперед. |
Для изменения имени клипа нужно сделать на нем двойной щелчок. Если нужно изменить границы какого-то клипа, нужно выделить его имя в списке, передвинуть треугольники в нужное положение, и щелкнуть по кнопке Update clip.
В окне Split Video вырежьте три отдельных куска для каждого канала и назовите их Вести, Спорт и СТС. Не меняя параметры в остальных окнах, завершите импорт видео. |
Что же есть в остальных окнах мастера? Следующая страница Encoding (кодирование) определяет параметры кодирования видео. На вкладке Encoding Profiles (профили кодирования) можно выбрать одну из двух версий проигрывателя (Flash 7 или Flash 8), а также нужную скорость канала связи, начиная от модемного (Modem quality) со скоростью 40 Кбит/с до широкополосной линии (700 Кбит/с):
Вкладка Video определяет способ кодирования видеоизображения (без учета звука). Если снять флажок Encode video, изображение не кодируется вообще. Список Video codec позволяет выбрать алгоритм кодирования, в поле Frame rate задается частота кадров, Same as FLA означает «такой же, как у FLA-файла. Поля Quality и Max data rate определяют качество изображения и скорость канала передачи данных. С помощью поля Key frame placement можно расставить ключевые кадры внутри видеоряда.
На вкладке Audio всего два параметра: флажок Encode audio (если его отключить, звук будет вырезан) и качество звука (Data rate).
Вкладка Crop and Resize позволяет обрезать поля видеофильма (Crop) и изменить размер кадра (Resize). Флажок Maintain aspect ratio лучше оставить включенным, так как при этом сохраняются пропорции изображения (aspect ratio).
При импорте файла без внедрения видео преобразуется к формату FLV, при этом в окне Encoding появится вкладка Cue Points (контрольные точки). В видеофайле можно отметить какие-то кадры, дать имена меткам и использовать их в программе.
Итак, после завершения импорта в библиотеку будут добавлены три символа типа Embedded video и соответствующие им три клипа типа MovieClip.
Определите имена видеоклипов для использования в ActionScript
(команда Linkage из контекстного меню):
|
Перейдите к кадру 1 слоя Программы и введите код:
chNames = ["vesti", "sport", "ctc"]; MAX = chNames.length; loadChannels(); function loadChannels() { for ( i=1; i<=MAX; i++ ) { name = "channel" + i; attachMovie(chNames[i-1], name, i); _root[name]._visible = false; _root[name].stop(); } } |
Добавьте к кадру 1 следующий код: _global.power = function () { tv.power = ! tv.power; if ( tv.power ) { tv.lamp.gotoAndStop("on"); channel ( tv.channel ); } else { tv.lamp.gotoAndStop("off"); obj = eval("channel" + tv.channel); obj._visible = false; obj.stop(); } } |
Добавьте к кадру 1 следующий код: _global.channel = function ( no ) { if ( ! tv.power ) return; if ( no < 1 ) no = MAX; if ( no > MAX ) no = 1; for ( var i=1; i<=MAX; i++ ) { obj = eval("channel" + i); if ( i == no ) { obj._visible = true; obj.play(); obj._x = tv.screenX; obj._y = tv.screenY; } else { obj._visible = false; obj.stop(); } } tv.channel = no; } |
Сохраните все клипы в формате FLV с именами vesti.flv, sport.flv и ctc.flv. |
Справа расположен список файлов, он прокручивается с помощью кнопок-стрелок на линейке. Каждый видеоклип имеет комментарий, который отображается под роликом при его проигрывании.
Мы не будем внедрять клип внутрь Flash-фильма, а загрузим его с диска (это возможно только для файлов в формате FLV). Таким образом, объем основного фильма будет небольшим.
При импорте в библиотеку и на сцену будет помещен стандартный компонент FLVPlayback предварительно скомпилированный клип, который поставляется вместе с программой Flash и служит для проигрывания Flash-видео. Другие компоненты можно найти на панели Components (меню WindowComponents)
Для проигрывателя можно выбрать одну из готовых «шкурок», которая определяет внешний вид кнопочной панели. «Шкурка» хранится в виде SWF-файла, который нужно поместить в той же папке, что и наш ролик.
Откройте файл PRACTICE\12\flv_player.fla. Войдите в меню FileImportImport video, выберите файл vesti.flv. На странице Deployment отметьте вариант Progressive download from a web server (загрузка с Web-сервера). На странице Skinning выберите понравившуюся «шкуру». |
Выделите проигрыватель на сцене, с помощью панели Properties увеличьте его ширину до 230 пикселей и переместите в левый верхний угол сцены. Откройте панель Parameters, если она еще не открыта в нижней части экрана (меню WindowsPropertiesParameters). Дайте компоненту имя player, по которому к нему можно обратиться из программы. Отмените автозапуск проигрывания исправьте значение параметра autoPlay на false. Просмотрите работу ролика. |
Под проигрывателем разместите текст Канал Вести (типа Dynamic Text) и дайте ему имя info. |
Добавьте новый слой Программа и присоедините к кадру 1 описание массивов, в которых хранятся имена видеофайлов
и комментарии:
files = ["vesti.flv", "sport.flv", "ctc.flv"]; infoLine = ["Канал Вести", "Канал Спорт", "Канал СТС"]; |
createEmptyMovieClip ( имя экземпляра, глубина );
Эта команда присоединяет к текущему клипу (в данном случае
к _root) новый пустой клип и располагает его
на заданной глубине.
Добавьте к кадру 1 код, создающий пустой клип-список на глубине 1:
createList(); function createList() { createEmptyMovieClip ( "list", 1 ); y0 = 10; list._x = 250; list._y = y0; } |
Список будем строить из имеющихся в библиотеке символов-клипов Элемент, которые имеют кодовое имя item. Внутри клипа Элемент есть динамическое текстовое поле itemName, в которое заносится имя файла.
Далее добавьте в функцию createList цикл, который создает
новые элементы списка и заполняет их именами из массива
files:
MAX = files.length; dy = 30; for(i=0; i<MAX; i++) { name = "item" + i; list.attachMovie("item", name, i); with ( list[name] ) { _y = dy*i; itemName.text = files[i]; } }Проверьте, как составляется список файлов. |
Элементы добавляются к списку list с помощью метода
attachMovie ( имя клипа, имя экземпляра, глубина );Элементы будут иметь имена item0, item1 и item2. Для того, чтобы элементы списка реагировали на щелчок мышью, к ним надо добавить обработчик onRelease.
Добавьте в конец цикла for строчку, которая назначает функцию playItem
обработчиком события release для
очередного элемента списка:
list[name].onRelease = playItem;
В конец функции createList допишите строчки
player.autoPlay = true; playFile(0);для того, чтобы задать начальное состояние и включить автозапуск. В самый конец кода кадра 1 добавьте функции function playItem() { no = this._name.substr(4); playFile ( no ); } function playFile ( no ) { player.contentPath = files[no]; info.text = infoLine[no]; }Проверьте работу списка файлов. |
loadVariables ( имя файла, имя клипа );
загружает переменные из файла в указанный клип;
loadVariablesNum ( имя файла, уровень );
загружает переменные из файла в корневой клип заданного уровня.
loadVariables ( "files.txt", "_root" );или, что то же самое,
loadVariablesNum ( "files.txt", 0 );
Остается разобраться, как хранятся переменные в таком файле. Они должны быть записаны в форме
&имя=значениеПеред каждым именем ставится знак & (амперсанд). Именно в таком виде передаются значения переменных на сервер при использовании метода GET (значения переменных в конце URL-адреса).
В нашем случае три имени файла можно записать как три переменные с именами name0, name1 и name2:
&name0=vesti.flv&name1=sport.flv&name2=ctc.flv
Создайте новый файл типа ActionScript File, скопируйте в него приведенный выше код (Ctrl+C копировать, Ctrl+V вставить) и сохраните под именем files.txt. |
В коде кадра 1 удалите или закомментируйте строчку, где задается массив files. Вместо нее добавьте такой
код
loadVariables("files.txt", "_root"); getData(); function getData() { files = new Array(); i = 0; while ( 1 ) { name = "name" + i; if ( this[name] == undefined ) break; files[i] = this[name]; i++; } createList(); }Запустите фильм. |
При запуске обнаруживается, что программа не нашла ни одной переменной. Дело в том, что вызов loadVariables дает команду начать загрузку переменных, но не дожидается ее выполнения. Таким образом, к моменту выполнения следующих команд файл еще не успел загрузиться, для этого требуется несколько кадров, которые надо «выждать».
К сожалению, функции loadVariables (и loadVariablesNum) не дают возможности узнать, когда чтение данных фактически закончилась и можно использовать введенные переменные. «Лобовой» выход вставить вызов loadVariables в кадр 1, а основной код через несколько кадров, нельзя считать красивым и грамотным решением.
Замените строчки loadVariables("files.txt", "_root"); getData();на такой код: lv = new LoadVars(); lv.load("files.txt"); lv.onLoad = getData;и проверьте работу фильма. |
Аналогично можно поступить и с комментариями в массиве infoLine, однако здесь есть одна проблема, связанная с русскими буквами. Они должны быть закодированы в формате URL (двухбайтовый формат, кодировка UNICODE, запись только через символы с ASCII-кодами от 0 до 127). Например, русская буква А кодируется как %D0%90, а буква Б как %D0%91. Закодировать русский текст в такой форме можно в Интернете в реальном времени. Вот как должны быть закодированы наши имена файлов и комментарии (переменные info0, info1 и info2):
&name0=vesti.flv&info0=%D0%9A%D0%B0%D0%BD%D0%B0%D0%BB+%D0%92%D0%B5%D1%81%D1%82%D0%B8 &name1=sport.flv&info1=%D0%9A%D0%B0%D0%BD%D0%B0%D0%BB+%D0%A1%D0%BF%D0%BE%D1%80%D1%82 &name2=ctc.flv&info2=%D0%9A%D0%B0%D0%BD%D0%B0%D0%BB+%D0%A1%D0%A2%D0%A1
Скопируйте в файл files.txt текст, показанный выше, и сохраните его. Закомментируйте (двумя знаками /) строчку кода,
где определяется массив infoLine. Добавьте в начало
функции getData код создания массива:
infoLine = new Array();
а внутрь цикла while запись в него нового элемента:
infoLine[i] = this["info"+i];Проверьте работу фильма. |
Язык XML предназначен для описания древовидных (многоуровневых) структур (баз данных). Такие структуры состоят из узлов. Каждый узел некоторый набор данных, он может иметь атрибуты (свойства) и текстовое содержание (произвольный текст).
Из программы на ActionScript можно
XML-файл состоит из отдельных тегов (команд разметки). Существуют парные теги, состоящие из двух частей (они обозначают начало и конец действия тега) и непарные, которые не содержат ничего внутри, не являются контейнерами. Рассмотрим пример:
<lib> <book author="Пушкин" title="Полтава" /> </lib>XML-документ включает один парный тег <lib> и соответствующий ему закрывающий тег </lib>. Внутри него помещается непарный тег <book ... />, у которого есть два атрибута:
Для работы с данными в XML-формате применяется встроенный объект XML, который можно создать так:
xml = new XML();Для создания XML-данных в памяти используются методы этого объекта createElement (создать элемент), createTextNode (создать текстовый узел) и appendChild (добавить потомка). Здесь мы подробно разберем, как раскодировать загруженный XML-файл.
Откройте файл files.xml из папки PRACTICE\12\FLV и изучите его. При выборе файла на диске в поле Тип файла нужно выбрать All files (показать все файлы). |
<lib> <video name="dames.flv" info="Разговор по-французски" /> <video name="boat.flv" info="На моторной лодке" /> <video name="blin.flv" info="После бани" /> <video name="kryak.flv" info="Утка" /> <video name="fish.flv" info="Рыбаки" /> <video name="bear.flv" info="Медведь" /> <video name="cow.flw" info="Корова в самолете" /> <video name="izum.flv" info="Скажи 'Изюм!'" /> <video name="whatdo.flv" info="Что делать?" /> <video name="shot.flv" info="Выстрел" /> <video name="understand.flv" info="Понимание" /> <video name="cigar.flv" info="Окурок" /> </lib>С точки зрения языка XML здесь есть один парный тег верхнего уровня lib, внутри которого записаны несколько непарных тегов video, имеющих атрибуты name и info.
Создадим объект XML и загрузим в него файл files.xml с диска:
xml = new XML(); xml.ignoreWhite = true; xml.load ( "FLV/files.xml" );Команда во второй строке означает, что пустые строки в файле будут игнорироваться.
Для обработки данных будем использовать событие load объекта XML, которое возникает после полной загрузки данных. Установим обработчик:
xml.onLoad = getData; function getData() { ... }В данном случае у объекта xml есть один дочерний узел lib. Чтобы получить на него ссылку, используем свойство firstChild (первый дочерний узел):
lib = xml.firstChild;
Дальше запишем в переменную videos массив, состоящий
из всех дочерних узлов lib:
video = lib.childNodes;
Каждый элемент массива этого имеет свойство nodeName
(имя узла), его можно использовать для проверки
данных у всех
«правильных» узлов должно быть имя video.
Чтобы «добраться» до атрибутов name и info каждого элемента используется запись
video[i].attributes.name
и
video[i].attributes.info
.
Замените строчки кода lv = new LoadVars(); lv.load("files.txt"); lv.onLoad = getData;на xml = new XML(); xml.ignoreWhite = true; xml.load ( "FLV/files.xml" ); xml.onLoad = getData;и измените функцию getData следующим образом: function getData() { k = 0; for(i=0; i<video.length; i++){ if ( video[i].nodeName == "video" ) { files[k] = video[i].attributes.name; info[k] = video[i].attributes.info; k ++; } } createList(); } |
Поскольку все видеоклипы находятся в папке FLV, нужно изменить адрес при загрузке файла в проигрыватель.
В функции playFile добавьте путь FLV/ к именам файлов в строчке
player.contentPath = "FLV/" + files[no];Проверьте ролик. |
Разместите у левой границы сцены линейку прокрутки символ Прокрутка из библиотеки. Дайте ему имя scrollBar (на панели Properties). |
_root.scroll ( "down" );а при щелчке по кнопке «вниз» ту же функцию, но с другим параметром:
_root.scroll ( "up" );Функцию scroll нужно написать где-то в коде, связанном с главным монтажным столом.
Прокрутка состоит в том, что меняется y-координата клипа-списка list, за один раз на величину, равную расстоянию по высоте между соседними элементами dy.
Добавьте в конец кода кадра 10 функцию прокрутки
function scroll ( dir ) { if ( dir == "up" ) list._y -= dy; else list._y += dy; } |
Создайте новый символ Маска, нарисуйте квадрат со стороной 20, установите на панели Properties координаты X=0 и Y=0. Задайте символу имя mask для использования в программе (Linkage из контекстного меню). |
Добавьте в конец функции createList (перед строчкой player.autoPlay=true; )
код создания маски:
attachMovie("mask", "mask", 10); with ( mask ) { _x = list._x; _y = list._y; _width = list.item1._width; _height = scrollBar._height; } list.setMask ( mask );Проверьте работу фильма. |
Измените функцию прокрутки так, чтобы список не уходил слишком далеко вниз и вверх:
function scroll ( dir ) { if ( dir == "up" ) list._y = Math.max ( list._y-dy, y0+mask._height-dy*MAX ); else list._y = Math.min ( list._y+dy, y0 ); } |
Внешние файлы | Объекты и классы |
© 2007 К. Поляков