# description: Wowza Media Server is a media server
Ну правильно, надо ж было пояснить :)
Дальше начинается просто вакханалия крючкотворства. Дело в том, что Adobe выблевнула в 2009 году «спецификацию» RTMP. Этот документ описывает некоторый протокол, который очень похож на RTMP и Adobe упорно называет то, что описывает этот документ, как RTMP. И более того: в документе сказано, что после прочтения этого документа, вы не имеете права реализовывать RTMP серверы иначе, кроме как по этому документу. Отступление на один байт от этого документа лишает вас права использовать этот документ.
levgem.livejournal.com
_items.remove(id);
log.info("after removing item {} contains: {}", id, _items.contains(id));
на Red5
after removing item 1 contains: true
на Wowza
after removing item 1 contains: false
то бишь, на Red5 почему-то элемент не хочет удаляться из ConcurrentHashMap
Ну да, я, конечно, криворукий. Но wowza мне это прощает, а red5 нет :(
Теперь нужно сидеть и напряженно медитировать, пока не придет догадка, что с этим делать :)
Однако оный RTMPClient не стабильный, переодически не коннектится, а когда коннектится, не всегда нормально общается с сервером. То чего-то не пришлет, то чего-то не примет. Отладка легче не стало.
А жаль, ибо тут можно было бы мощные интеграционные тесты замутить.
Либо залезть в сорцы, разобраться и пофиксить. Либо сделать бот-клиента на флэше для тех же целей. Либо забить на все это и отлаживать многими кликами. Думаю.
public function answerInvitation(visitorID : String, accepted : Boolean) : void
{
service.call("answerInvitation", null, visitorID, accepted);
}
беру на Wowza
public void answerInvitation(IClient client, RequestFunction function, AMFDataList params)
{
String visitorID = params.getString(PARAM1);
boolean accepted = params.getBoolean(PARAM2);
log.info("answerInvitation {} {}", visitorID, accepted);
}
и, внезапно, фигня — visitorID null
Поглядел params.toString, а там
[0] answerInvitation
[1] 3.0
[2] null
[3] null
[4] 3 // visitorID
[5] true // accepted
пришлось брать параметры не таким вот очевидным способом
String visitorID = params.getString(PARAM1);
boolean accepted = params.getBoolean(PARAM2);
а вот таким неочевидным
String visitorID = params.getString(PARAM2);
boolean accepted = params.getBoolean(PARAM3);
Что-то не припомню таких фокусов в прошлых проектах.
Теперь, во-первых, нифига не известно, из какого класса идет лог, ибо для всех логов одна категория — "server comment". Во-вторых, так у них не работает:
log.info("some {} info {}", param1, param2);
а надо так
log.info("some " + param1 + " info " + param2);
А чтобы увидеть таки класс, надо делать так:
log.info("some " + param1 + " info " + param2, getClass().toString(), "");
причем там еще третий параметр, который мне не нужен, и куда мне приходится передавать пустую строку.
Ну у меня просто не остается другого вывода, как сделать еще одну обертку, вокруг их обертки, чтобы не приходилось добавлять getClass().toString(), "" в каждый log.info
Придется делать отдельный проект с отдельным флэш-клиентом только для того, чтобы прояснить этот момент.
Но это ерунда в сравнении с тем, что Wowza не поддерживает передачу типизированных объектов, из-за чего и приходится передавать везде Object или Array :)
Но вот теперь заморочка с Wowza. Вы уже догадались, что там тоже свой кастомный логгинг :) WMSLoggerFactory и WMSLogger :) И оный логгер является наследником org.apache.log4j.Logger.
И вот теперь мне надо думать, как бы свести к общему типу эти фабрики и логгеры, чтобы и из Red5 модуля и из Wowza модуля передать в red-wowza-независимый модуль какую-нибудь такую фабрику, что б там работала :)
Пока пытаюсь запустить в Wowza модуле org.slf4j.LoggerFactory и org.slf4j.Logger. Они вроде бы и работают, но в консоль выводят что-то загадочное и непонятное. Это потому, что у вовзы есть свой log4j.properties, весьма навороченый. И мне сейчас надо разобраться, как бы переопределить эти настройки в своем приложении.
Я надеялся, что это не так, но увы: wowzamedia.com
Сама по себе необходимость делать класс из объекта не так печалит. Печалит, что сериализация корректно работает на Red5 и FMS, но из-за вовзы от нее приходится отказываться и работать с нетипизированными объектами.
В итоге на клиенте приходится делать что-то такое:
public function onServerData(user : Object) : void
{
var myUser : UserVO;
if(user is UserVO)
{
// data from FMS or Red5
myUser = user;
}
else
{
// data from Wowza
myUser = UserVO.createFromRawData(user);
}
}
— запуск сервера самый быстрый у wowza, медленне у red5, самый медленный у fms (правда это включая запуск админ-сервера)
— коннект приложения к wowza и red5 примерно одинаково быстрый, к fms чутка медленне, заметно на глаз
Ага, вот оно. Значит нормальной AMF сериализации и быть не может.
Но вот самого разумного поведения — иметь и live stream, который бы не писался принудительно в файл, и возможность писать в файл, когда это нужно — такого поведения нет. На FMS это по дефолту без всяких настроек.
wowzamedia.com не могу понять этой фигни. Где же тут live-but-record-on-demand ?
Red5 неправ, так не хорошо.
Если бы Red5 не был таким хилым, я бы с удовольствием под него писал.
Wowza требует рута при установке, ставиться в жестко заданый каталог, который нельзя поменять, требует рута при запуске.
Вывод: вавзу делали виндузятники в своем типичном виндузятском стиле.
void methodToCallFromClient(String param1, MyCustomClass param2)
десериализация проходит где-то внурях, а в мой метод сразу приходят готовые объекты нужного мне типа.
На вовзе это как-то не так.
// receiving an object from the client
public void c2sParamsObject(IClient client, RequestFunction function, AMFDataList params)
{
AMFDataObj param1 = (AMFDataObj)getParam(params, PARAM1);
// direct method for getting object properties
String val1 = param1.getString("val1");
int val2 = param1.getInt("val2");
boolean val3 = param1.getBoolean("val3");
Date val4 = param1.getDate("val4");
}
то бишь, мне даются некие API функции, с помощью которых я сам должен вынять из пришедших данных то, что мне надо. Наверное это дает лучшую производительность. Но вот восторга у меня не вызывает.
Документация большей частью про стриминг и про всякие настройки. Почти все примеры — клиентский код. Кроме одного единственного, где-все таки показано, какой код надо написать на сервере, чтобы общаться с клиентом.
Однако желание что-либо писать сейчас под вовзу пропало напрочь, испортили они мне настроение. Но написать надо :(
State, конечно же, обязательный. И ежели у меня Country Беларусь, то мне предлагается выбрать State из выпадающего списка, где перечислены штаты для США, Канады, Японии и Китая. Так что будет у меня Belarus/Zhejiang Sheng. Я не виноват, сами этого захотели.
Ну а без лицензии сервер даже не запустишь.
mkdir: cannot create directory `/usr/local/WowzaMediaServer-2.1.2': Permission denied
mkdir: cannot create directory `/usr/local/WowzaMediaServer-2.1.2/applications': No such file or directory
mkdir: cannot create directory `/usr/local/WowzaMediaServer-2.1.2/logs': No such file or directory
./WowzaMediaServer-2.1.2.tar.bin: line 671: /usr/local/WowzaMediaServer-2.1.2.tar.gz: Permission denied
ln: creating symbolic link `/usr/local/WowzaMediaServer': Permission denied
./WowzaMediaServer-2.1.2.tar.bin: line 675: cd: /usr/local/WowzaMediaServer-2.1.2: No such file or directory
gzip: ../WowzaMediaServer-2.1.2.tar.gz: No such file or directory
tar: ../WowzaMediaServer-2.1.2.tar: Cannot open: No such file or directory
tar: Error is not recoverable: exiting now
cp: cannot stat `bin/WowzaMediaServer': No such file or directory
cp: cannot stat `bin/WowzaMediaServerd': No such file or directory
Наглость, однако. Если бы не острая нужда, то на этом знакомство с вовзой и закончилось бы. А так придется ставить из-под рута, да еще не в то место, куда я хотел :(
Может у меня стиль работы неправильный?