Разрабатывать под FMS можно двумя способами:
Надо сказать, что Адоб сделал все возможное, чтобы первый способ работал. Действительно, можно писать полноценные мультимедиа и многопользовательские приложения почти не разбираясь в FMS, мельком проглядев документацию. Порог вхождения в разработку очень низкий.
Адоб постарался, чтобы максимум возможностей были доступны из клиентского кода, и чтобы разработчик мог избегать написания серверного кода. Учитывая, что целевая аудитория Адоба -- флэш-разработчики -- в основном специалисты по клиентской части, и не многие из них хотят и могут писать серверный код, то такой подход вполне оправдан.
Но уж если пришлось писать серверный код, то и тут можно не заморачиваться, не вникать в особенности языка ServerSide ActionScript. Можно просто просмотреть документацию и примеры кода, и дальше самому писать по наитию. Это работает :) Но если уж хочется заморочиться, то можно копнуть глубже.
Итак, на стороне клиента нас интересуют 6 классов: NetConnection, NetStream, SharedObject, Camera, Microphone, Video.
Класс NetConnection обеспечивает соединение с FMS сервером. Соединение позволяет вызывать методы на стороне сервера и представляет серверу возможность вызывать методы у себя.
Внутри одного соединения может быть неограниченное количество потоков NetStream. Поток может передавать видео, аудио и другие бинарные данные, но только в одном направлении. Чтобы передавать и получать данные нужно как минимум два потока.
Обычно создается один экземпляр NetConnection и нужное количество экземпляров NetStream. Хотя никто не запрещает создать несколько NetConnection к разным FMS-приложениям и разным серверам.
Класс SharedObject позволяет работать не только с клиентскими SharedObjects, но и серверными. Хотя API у них немного разные.
Классы Camera и Microphone, очевидно, позволяют захватить видео с вебкамеры и звук с микрофона, и через NetStream публиковать их на сервер. Класс Video позволяет показать видео, полученное с сервера.
Вот и все, собственно.
Установка соединения с FMS сервером -- штука простая. Главное знать URI, куда соединяться. А URI этот выглядит так:
protocol://host:port/appname/instanceName
Протокол может быть один из: rtmp, rtmpe, rtmps, rtmpt, and rtmpte.
Хост -- доменное имя или IP адресс
Порт можно не указывать если он дефолтный (1935)
appname -- имя приложения на fms сервере
instanceName -- экземпляр приложения
Одно приложение может иметь несколько экземпляров, которые работают независимо друг от друга. Каждый экземпляр имеет своих клиентов, потоки, SharedObjects и т.д.
package
{
import flash.display.Sprite;
import flash.events.IOErrorEvent;
import flash.events.NetStatusEvent;
import flash.events.SecurityErrorEvent;
import flash.net.NetConnection;
import flash.net.ObjectEncoding;
public class Sample_01_Connect extends Sprite
{
public var nc : NetConnection;
// constructor
public function Sample_01_Connect()
{
nc = new NetConnection();
//nc.objectEncoding = ObjectEncoding.AMF0;
nc.addEventListener(NetStatusEvent.NET_STATUS, OnNetStatus);
nc.addEventListener(IOErrorEvent.IO_ERROR, OnIOError);
nc.addEventListener(SecurityErrorEvent.SECURITY_ERROR, OnSecurityError);
nc.connect('rtmp://localhost/test', {});
//nc.close();
}
protected function OnNetStatus(e:NetStatusEvent):void
{
switch(e.info.code)
{
case "NetConnection.Connect.Success":
trace('Connection to ' + nc.uri + ' success');
break;
case "NetConnection.Connect.Rejected":
trace('Connection to ' + nc.uri + ' rejected');
break;
case "NetConnection.Connect.Failed":
trace('Failed connect to ' + nc.uri);
break;
case "NetConnection.Connect.Closed":
trace('Connection to ' + nc.uri + ' closed');
break;
default: trace(e.info.code);
}
}
private function OnIOError(e:IOErrorEvent):void
{
trace("IO error: " + e.text);
}
private function OnSecurityError(e:SecurityErrorEvent):void
{
trace("Security error: " + e.text);
}
}
}
Как видите, код простой и очевидный, комментировать тут особо нечего.
Эта задача хорошо знакома любому флэшеру. Наверное, нет такого флэш-разработчика, который не написал бы свой видеоплейер :) Так что примера кода тут не будет. Зато будет некоторая специфика FMS.
После того, как мы соеденились с FMS сервером, можно создавать экземпляр NetStream и вызывать метод play( name:Object, start:Number, len:Number, reset:Object):void
Обязательный параметр только первый -- имя файла. Далее можно задать, с какой позиции проигрывать файл и какую часть файла проигрывать. Последний параметр связан с плейлистами.
Плейлисты -- фича, специфичная для FMS. Фишка в том, что можно вызвать play несколько раз подряд, передавая четвертым параметром false (кроме первого вызова). Новые видеофайлы будут становится в очередь, формируя плейлист.
stream = new NetStream(nc);
stream.play( "advertisement", 0, 30 );
stream.play( "video1", 10, -1, false );
stream.play( "video2", 0, -1, false );
stream.play( "video3", 30, 120, false);
Немаловажная задача -- определение длинны видео файла. Это обязательно нужно, чтобы реализовать ползунок для отображения и изменения текущей позиции воспроизведения. Обычно длину видео берут из метаданных. Но может статься, что она там не будет указана (это зависит от того, каким софтом создавался файл).
Но у FMS есть другой способ. Длину видео можно определить на стороне сервера следующим кодом
var length = Stream.length("flv_file")
и потом передать эту инфу клиенту.
Это тоже очень простая задача. Опять же, после соединения с сервером можно создавать NetStream, захватывать камеру и микрофон и публиковать с помощью следующего кода:
var cam : Camera = Camera.getCamera();
var mic : Microphone = Microphone.getMicrophone();
var ns : NetStream = new NetStream(nc);
ns.attachCamera(cam);
ns.attachAudio(mic);
ns.publish("myStream", "live");
На публикуемый поток могут подписаться много других клиентов, получать и отображать его.
var ns : NetStream = new NetStream(nc);
ns.play("myStream");
var vid : Video = new Video();
vid.attachNetStream(nsPlayer);
addChild(vid);
Вместо публикации видео в live его можно записывать в файл. Разница будет только во втором параметре метода publish()
ns.publish("myStream", "record");
Вместо видео можно передавать бинарные данные, для этого нужно использовать метод send(). Правда для этого NetStream все равно должен что-то публиковать, и данные будут получать те, кто подписан на эту публикацию.
// publisher code
var ns : NetStream = new NetStream(nc);
ns.publish("myStream", "live");
ns.send("SomeHandler", argument1, argument2);
// subscriber code
ns : NetStream = new NetStream(nc);
ns.client = new NsListener();
ns.play("myStream");
class NsListener()
{
public function SomeHandler(argument1 : Object, argument2 : Object) : void
{
trace('SomeHandler ' + argument1 + ' ' + argument2);
}
}
Для работы с ServerSide SharedObject тоже нужно установленное соединение с FMS и экземпляр объекта NetConnection.
var nc : NetConnection;
so : SharedObject = SharedObject.getRemote('myData', nc.uri, persistence);
so.addEventListener(SyncEvent.SYNC, OnSyncEvent);
so.addEventListener(NetStatusEvent.NET_STATUS, OnNetStatus);
so.addEventListener(AsyncErrorEvent.ASYNC_ERROR, OnAsyncError);
so.connect(nc);
//so.close();
private function OnSyncEvent(e:SyncEvent):void
{
for(var i:int = 0; i < e.changeList.length; i++)
{
var desc:Object = e.changeList[i];
trace(desc.name + ' ' + desc.code);
}
}
private function OnNetStatus(e:NetStatusEvent):void
{
}
private function OnAsyncError(e:AsyncErrorEvent):void
{
}
В отличие от локального SharedObject, читать данные нужно с помощью метода getProperty() а писать с помощью setProperty().
Тут важно обработать SyncEvent. Оно срабатывает один раз, когда устанавливается соединение с ShareObject, и потом срабатывает каждый раз, когда какой-либо клиент меняет там данные.
SyncEvent содержит массив объектов со следующими данными:
Коды могут быть следующие:
Comments
Anonymous (not verified)
Sun, 01/09/2011 - 18:55
Permalink
Я работаю с wowza у вас он не
Я работаю с wowza у вас он не описан,но думаю принципиальной разницы быть не должно.
У меня стоит задача сделать текстуру с видео и наложить ее на грань трехмерного объекта
Для этого, прежде когда я работал с обычным, не потоковым видео использовал bitmapdata.draw
При попытке использовать потоковое видео столкнулся со следующей проблемой:
Нарушение изолированной среды: BitmapData.draw: .../some.swf не может осуществить доступ к rtmp://video.somedomain.net:1935/vod/. Не предоставлен доступ к файлам политики.
Насколько я понял из туториалов все дело в настройках приложения application.xml
в узле <клиент> нужно добавить звездочки в к видео и аудио узлам
"<.Client.>
<.IdleFrequency.>-1<./IdleFrequency.>
<.Access>
<.StreamReadAccess.>*
<.StreamWriteAccess>*<./StreamWriteAccess.>
<.StreamAudioSampleAccess>*<./StreamAudioSampleAccess>
<.StreamVideoSampleAccess>*<./StreamVideoSampleAccess>
<.SharedObjectReadAccess>*<./SharedObjectReadAccess>
<.SharedObjectWriteAccess>*<./SharedObjectWriteAccess>
<./Access>
<./Client>"
Я менял этот application в трех места в корневом conf в conf/vod а также в applications/vod (хотя я вроде бы читал, что все настройки приложений должны быть в conf) К сожалению мне это не помогло (
Add new comment