Потоковое видео с мобильного телефона в FMS с использованием эфира
Я использую Air для потоковой передачи веб-камеры в FMS (Flash Media Server), так как вы знаете, что на настольном компьютере это не проблема, но могу ли я осуществлять потоковую передачу с мобильных устройств (Android, iOS)? вот мой код:
var nc:NetConnection = new NetConnection();
var bandwidth:int = 0;
var quality:int = 50;
var camera:Camera = Camera.getCamera();
camera.setQuality(bandwidth, quality);
camera.setMode(430,320,15, true);
var video:Video = new Video();
video.attachCamera(camera);
addChild(video);
video.width = 430;
video.height = 320;
nc.connect("rtmp://***");
nc.addEventListener(NetStatusEvent.NET_STATUS, netStatusHandler);
function netStatusHandler(event:NetStatusEvent):void{
if (event.info.code == "NetConnection.Connect.Success")
{
label10.text = 'Connected';
var ns:NetStream = new NetStream(nc);
ns.attachCamera(camera);
ns.publish("NewStream1", "live");
}
}
У меня нет FMS для тестирования, кто-нибудь пробовал это или, по крайней мере, есть ли способ проверить это без покупки FMS?
2 ответа
Я сделал потоковую передачу из мобильных приложений AIR через медиа-сервер Wowza. Стандартный потоковый код должен работать, просто обратите внимание, что видео H.264 не поддерживается в iOS через Flash.
Да, ты можешь!
Я сконцентрировался на этой теме некоторое время, и теперь я могу опубликовать поток на сервере потокового мультимедиа и подписаться на него. Мой сервер потокового мультимедиа - Red5, он бесплатный и отличный, если вы попробуете его использовать, вы узнаете.Red5 был написан Java, но он был написан для Flash, и его клиент использует Flash или Flex.
Как вы знаете, NetConnection и NetStream из ActionScript являются отличными, и вы можете использовать их для публикации потока в Red5 или FMS, вы также можете использовать их для подписки потока.
Если вы хотите написать мобильное приложение с ActionScript, вы можете обратиться по этой ссылке. http://help.adobe.com/en_US/flex/mobileapps/index.html Во-первых, вам нужно создать мобильное приложение Flex, в первом представлении вы можете вставить приведенный ниже код. И когда вы сможете опубликовать поток, вы знаю, как подписаться.
Это мой основной код, в этом коде я использовал сервис adobe stratus для тестирования моего проекта. Я извиняюсь за возможность помочь вам так много:
import mx.core.UIComponent;
import mx.events.FlexEvent;
import org.osmf.elements.VideoElement;
import spark.components.VideoDisplay;
private var netConnection:NetConnection = null;
private var netStream:NetStream = null;
private var netGroup:NetGroup = null;
private var video:Video = null;
private var sequenceNumber:uint = 0;
//Stratus 服务器地址
private const SERVER:String = "rtmfp://stratus.adobe.com/";
//开发者Key,请使用你申请的Key
private const DEVKEY:String = "1710124cbf69e3f25b780c13-d6cbf2cb35a1";
//组的名字,名字要唯一
private const GROUP_PREFIX:String = "www.flextheworld.com.stratus2.demo";
//[Bindable]的作用是进行绑定,如果定义的值改变那么所有被它影响的引用都将改变其值,会有事件发送以获得引用的改变
[Bindable]
private var connected:Boolean = false;
[Bindable]
private var joinedGroup:Boolean = false;
private var cam:Camera;
protected function creationCompleteHandler(event:FlexEvent):void
{
groupName.text = "channel" + (int(Math.random() * 899) + 101);
cam = Camera.getCamera();
if(cam){
cam.setMode(width, width, 25);
cam.setQuality(144000,85);
cam.setKeyFrameInterval(5);
cam.setLoopback (false);
var video: Video = new Video(cam.width, cam.height);
ui.width = video.width;
ui.height = video.height;
/*ui.addChild(video);*/
video.attachCamera(cam);
}
}
/**
* NetStream和Group的事件响应
* */
private function netStatusHandler(e:NetStatusEvent):void
{
switch(e.info.code)
{
case "NetConnection.Connect.Success": //与Stratus链接成功,开始创建/进入组
onConnect();
break;
case "NetConnection.Connect.Closed":
case "NetConnection.Connect.Failed":
case "NetConnection.Connect.Rejected":
case "NetConnection.Connect.AppShutdown":
case "NetConnection.Connect.InvalidApp":
onDisconnect();
break;
case "NetStream.Connect.Success": //Net Stream 链接成功
onNetStreamConnect();
break;
case "NetStream.Connect.Rejected": // e.info.stream
case "NetStream.Connect.Failed": // e.info.stream
doDisconnect();
break;
case "NetGroup.Connect.Success": // e.info.group
onNetGroupConnect();
break;
case "NetGroup.Connect.Rejected": // e.info.group
case "NetGroup.Connect.Failed": // e.info.group
doDisconnect();
break;
case "NetGroup.Posting.Notify": // 收到信息
case "NetStream.MulticastStream.Reset":
case "NetStream.Buffer.Full":
break;
case "NetGroup.SendTo.Notify": // e.info.message, e.info.from, e.info.fromLocal
case "NetGroup.LocalCoverage.Notify": //
case "NetGroup.Neighbor.Connect": // e.info.neighbor
case "NetGroup.Neighbor.Disconnect": // e.info.neighbor
case "NetGroup.MulticastStream.PublishNotify": // e.info.name
case "NetGroup.MulticastStream.UnpublishNotify": // e.info.name
case "NetGroup.Replication.Fetch.SendNotify": // e.info.index
case "NetGroup.Replication.Fetch.Failed": // e.info.index
case "NetGroup.Replication.Fetch.Result": // e.info.index, e.info.object
case "NetGroup.Replication.Request": // e.info.index, e.info.requestID
default:
break;
}
}
private function doConnect():void
{
if(joinedGroup){
doDisconnect()
return;
}
startBtn.label = "链 接 中";
startBtn.enabled = false;
//updateStatus("Connecting to \"" + SERVER + "\"");
netConnection = new NetConnection();
//传入的两个参数分别为事件类型和监听器,这个监听器接收第一个参数定义的事件类型且不能有返回值。
netConnection.addEventListener(NetStatusEvent.NET_STATUS, netStatusHandler);
netConnection.connect(SERVER + DEVKEY);
}
/**
* 与Stratus 链接成功后触发
* */
private function onConnect():void
{
//GroupSpecifier 类用于构造可传递给 NetStream 和 NetGroup 构造函数的不透明的 groupspec 字符串
var groupSpecifier:GroupSpecifier;
//updateStatus("与Stratus链接成功\n");
connected = true;
//定义组,根据用户输入的groupName构造了唯一的GroupSpecifier
groupSpecifier = new GroupSpecifier(GROUP_PREFIX + groupName.text);
//允许多播
groupSpecifier.multicastEnabled = true;
//允许发送数据
groupSpecifier.postingEnabled = true;
//打开频道,只有打开服务器通道,服务器才能将支持功能提供给组成员。
groupSpecifier.serverChannelEnabled = true;
//创建netStream与用户组的链接,我们用他来发送视频和音频流
/*
* groupspecWithAuthorizations()返回可传递给 NetStream 和 NetGroup 构造函数的不透明的 groupspec 字符串,包括授权。
* 在对等多播组中发布或播放,需指定 groupspec字符串
*/
netStream = new NetStream(netConnection, groupSpecifier.groupspecWithAuthorizations());
netStream.addEventListener(NetStatusEvent.NET_STATUS, netStatusHandler);
//加入用户组
//NetGroup 类的实例表示 RTMFP组中的成员资格,此类可以监视服务质量,发布,直接路由(发送),对象复制
netGroup = new NetGroup(netConnection, groupSpecifier.groupspecWithAuthorizations());
netGroup.addEventListener(NetStatusEvent.NET_STATUS, netStatusHandler);
//updateStatus("加入用户组 \"" + groupSpecifier.groupspecWithAuthorizations() + "\"\n");
}
/**
*
* NetStraeam链接到用户组后触发
* */
private function onNetStreamConnect():void
{
//加载话筒
netStream.client = this;
var mic:Microphone = Microphone.getMicrophone();
if(mic)
{
mic.codec = SoundCodec.SPEEX;
mic.setSilenceLevel(0);
netStream.attachAudio(mic);
//updateStatus("话筒设置完毕\n");
}
//加载视频,并发布视频和话筒
publishVideo();
}
/**
* 发布视听流
* */
private function publishVideo():void{
netStream.attachCamera(cam)
//发布名字为stream 的流。这个部分这里就不讲解了,在原来的p2p教程里有详细说明
netStream.publish("stream");
}
private function onNetGroupConnect():void
{
startBtn.label = "直 播 中";
startBtn.enabled = true;
//加入用户组成功
joinedGroup = true;
}
/**
* 断开链接
* */
private function doDisconnect():void
{
if(netConnection){
startBtn.label = "停 止 中";
startBtn.enabled = false;
netConnection.close();
}
}
/**
* netconnection断开后执行
* */
private function onDisconnect():void
{
startBtn.label = "开始 直 播";
startBtn.enabled = true;
netConnection = null;
netStream = null;
netGroup = null;
connected = false;
joinedGroup = false;
}
]]>
</fx:Script>
<s:VGroup paddingTop="10" paddingLeft="10" paddingRight="10" id="cameraDisplay" width="100%" >
<s:Label fontSize="30" text="直播频道" />
<s:TextInput id="groupName" width="100%" />
<mx:UIComponent id="ui" />
<s:Group width="100%">
<s:layout>
<s:HorizontalLayout horizontalAlign="center" paddingTop="20" />
</s:layout>
<s:Button id="startBtn" fontSize="60" chromeColor="#9F2A2F" label="开 始 直 播" click="doConnect()" />
</s:Group>
</s:VGroup>