flex4+fms3.5+cs4开发实时音视频直播及点播详解
开发工具及环境:
1)flash builder4
2)flash cs4
3)flash media server3.5
fms部分
fms是adobe的流媒体服务器,不过是收费的,价格大概是oracle的一半,不过还是觉得挺贵的。adobe提供控制连接数的开发人员版,除了这点具体和完全版一样。服务器的配置网上很多,大家一搜就一大把。
其中关键的是:
由于需求是不仅要提供直播,而且还能点播历史音视频。而as的NetStream的publish方法提供的录制功能是将录制的视频放在直播的同一个文件夹下,所以要需要改一下fms配置。
1)fms的dvr默认是关闭的,需要修改C:/Program Files/Adobe/Flash Media Server 3.5/applications/live/main.far里的Application.xml,将文件中的
<StreamManager>
<StreamRecord override="no">false</StreamRecord>
</StreamManager>
改为
<StreamManager>
<StreamRecord override="yes">true</StreamRecord>
</StreamManager>
修改后重新加入main.far中
2)fms默认是将直播与点播文件目录分开的(live和vod),但是视频录制是在live文件加下,所以我们要修改点播目录
C:/Program Files/Adobe/Flash Media Server 3.5/conf/fms.ini文件中将
VOD_DIR 设置为 C:/Program Files/Adobe/Flash Media Server 3.5/applications/live
这样就可以实现直播点播同文件夹共存了
3)配置虚拟目录
打开C:/Program Files/Adobe/Flash Media Server 3.5/applications/live/Application.xml在<VirtualDirectory>中加入
<Streams>/;${VOD_COMMON_DIR}</Streams>
<Streams>/;${VOD_DIR}</Streams>
补充:如果在flex中直播视频时抛出noAccess错误,请在服务器上给录制机分配写入的权限。
通过以上配置fms就完成了
flex部分
<?xml version="1.0" encoding="utf-8"?>
<s:WindowedApplication xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx" width="" height=""
creationComplete="init_creationCompleteHandler(event)"
closing="unonload()">
<s:layout>
<s:BasicLayout/>
</s:layout>
<fx:Style source="media.css"/> <fx:Script>
<!--[CDATA[
import flash.events.NetStatusEvent;
import flash.net.NetConnection;
import flash.net.NetStream; import mx.collections.ArrayCollection;
import mx.controls.Alert;
import mx.controls.Text;
import mx.events.FlexEvent; private var nc:NetConnection;
private var ns:NetStream;
private var vi:Video;
private var cam:Camera;
private var microphone:Microphone;
private var fmsArr:ArrayCollection=new ArrayCollection([]);
private var sharedObject:SharedObject=SharedObject.getLocal("com.ue"); /**
* 初始化
*/
protected function init_creationCompleteHandler(event:FlexEvent):void{
var loader:URLLoader = new URLLoader();
loader.dataFormat=URLLoaderDataFormat.VARIABLES;
loader.addEventListener(Event.COMPLETE, loader_complete);
loader.load(new URLRequest("global.txt")); function loader_complete(e:Event):void {
var variables:URLVariables=new URLVariables(loader.data);
trace(variables["servers"]); var serversArr:Array = variables["servers"].toString().split("@#@");
for(var i:int=;i<serversArr.length;i++){
var server:String = serversArr[i];
var sArr:Array = server.toString().split("$#$"); fmsArr.addItem({label:sArr[], value:sArr[]});
}
} getCookie();
} public function getCookie():void{
if(sharedObject.data["pmhidh"]!=null){
pmhID.text = sharedObject.data["pmhidh"];
}
if(sharedObject.data["spfwq"]!=null){
trace(sharedObject.data["spfwq"]);
fms.selectedItem = sharedObject.data["spfwq"];
}
if(sharedObject.data["yl"]!=null){
slider.value = sharedObject.data["yl"];
} } /**
* 开始直播
*/
protected function startButton_clickHandler(event:MouseEvent):void{ startButton.enabled=false;
stopButton.enabled=true;
nc = new NetConnection();
nc.addEventListener(NetStatusEvent.NET_STATUS,connectServerHander);
nc.client = this; trace(fms.selectedItem.label);
nc.connect(fms.selectedItem.value); slider.enabled=true;
}
/**
* 回调函数
*/
public function connectServerHander(evt:NetStatusEvent):void{
cam = Camera.getCamera();
microphone = Microphone.getMicrophone(); if(microphone!=null){
microphone.setSilenceLevel();//总是收集音频
microphone.rate=;
}else{
Alert.show("无法链接到麦克风!");
} if(cam != null){
cam.setMode(,,);
cam.setQuality(,);
ns = new NetStream(nc);
ns.attachCamera(cam);
ns.attachAudio(microphone);
ns.publish(pmhID.text,"append"); vi = new Video();
vi.width = player.width;
vi.height = player.height;
vi.attachCamera(cam);
player.addChild(vi); }else{
Alert.show("无法链接到摄像头!");
}
}
/**
* NetConnection回调函数
*/
public function onBWDone():void{} /**
* 保存音视频文件
*/
// protected function browse_clickHandler(event:MouseEvent):void{
// var file:File = new File();
// file.addEventListener(Event.SELECT,dirSelected);
// file.browseForSave("另存为");
// function dirSelected(e:Event):void {
// trace(file.nativePath);
// filefilePath.text = file.nativePath;
// }
// } /**
* 音量控制
*/
protected function slider_changeHandler(event:Event):void{
microphone.gain = slider.value;
} /**
* 停止发布
*/
protected function stopButton_clickHandler(event:MouseEvent):void{
ns.close();
vi.visible=false;
startButton.enabled=true;
stopButton.enabled=false;
} /**
* 关闭窗口触发事件,保存配置
*/
public function unonload():void{
if(sharedObject!=null){
sharedObject.clear();
}
if(sharedObject.data["pmhidh"]==null){
sharedObject.data["pmhidh"] = pmhID.text;
}
if(sharedObject.data["spfwq"]==null){
sharedObject.data["spfwq"] = fms.selectedItem;
}
if(sharedObject.data["yl"]==null){
sharedObject.data["yl"] = slider.value;
}
sharedObject.flush();
} ]]-->
</fx:Script> <fx:Declarations>
<!-- 将非可视元素(例如服务、值对象)放在此处 -->
</fx:Declarations>
<s:Panel width="100%" height="100%" x="" y="" id="panel1">
<s:layout>
<s:VerticalLayout paddingLeft="" paddingRight="" paddingBottom="" paddingTop="" requestedRowCount=""/>
</s:layout>
<s:VGroup width="" height="" paddingTop="" paddingBottom="" paddingRight="" paddingLeft="">
<s:HGroup width="" height="" paddingLeft="" paddingTop="" paddingBottom="" paddingRight="">
<s:BorderContainer width="" height="">
<s:VideoDisplay width="" height="" scaleMode="letterbox" id="player" x="" y=""/>
</s:BorderContainer>
<s:BorderContainer width="" height="">
<s:VGroup width="" height="" paddingLeft="" paddingTop="" paddingBottom="" paddingRight="" gap="" x="" y="">
<s:Label text="拍卖会ID号:" height="" id="pmhIDLabel"/>
<s:TextInput id="pmhID"/>
<s:Label text="视频服务器:" height=""/>
<s:ComboBox id="fms" dataProvider="{fmsArr}"/>
<s:Label text="音量" height=""/>
<s:HSlider id="slider" enabled="false" change="slider_changeHandler(event)" minimum="" maximum="" stepSize=""/>
</s:VGroup>
</s:BorderContainer>
</s:HGroup>
<s:HGroup width="" height="" paddingTop="" paddingBottom="" paddingRight="" paddingLeft="" verticalAlign="middle" textAlign="center">
<s:Button id="startButton" label="开始发布" click="startButton_clickHandler(event)"/>
<s:Button label="停止发布" id="stopButton" enabled="false" click="stopButton_clickHandler(event)"/>
</s:HGroup>
</s:VGroup>
</s:Panel>
</s:WindowedApplication>
效果如下:
flash部分/点播代码
import flash.net.*;
import flash.events.*; var loader:URLLoader = new URLLoader();
loader.dataFormat=URLLoaderDataFormat.VARIABLES;
loader.addEventListener(Event.COMPLETE, loader_complete);
loader.load(new URLRequest("media2.txt")); function loader_complete(e:Event):void {
var variables:URLVariables=new URLVariables(loader.data); myVideo2.source=variables["source"];
}
myVideo2.isLive=false;
效果如下:
flash部分/直播代码
import flash.net.*;
import flash.events.*; var loader:URLLoader = new URLLoader();
loader.dataFormat=URLLoaderDataFormat.VARIABLES;
loader.addEventListener(Event.COMPLETE, loader_complete);
loader.load(new URLRequest("media.txt")); function loader_complete(e:Event):void {
var variables:URLVariables=new URLVariables(loader.data); myVideo.source=variables["source"];
} myVideo.isLive=true;
效果如下:
flex4+fms3.5+cs4开发实时音视频直播及点播详解的更多相关文章
- 音视频入门-11-PNG文件格式详解
* 音视频入门文章目录 * PNG 文件格式解析 PNG 图像格式文件由一个 8 字节的 PNG 文件署名域和 3 个以上的后续数据块(IHDR.IDAT.IEND)组成. PNG 文件包括 8 字节 ...
- 音视频入门-14-JPEG文件格式详解
* 音视频入门文章目录 * JPEG 文件格式解析 JPEG 文件使用的数据存储方式有多种.最常用的格式称为 JPEG 文件交换格式(JPEG File Interchange Format,JFIF ...
- 各种音视频编解码学习详解 h264 ,mpeg4 ,aac 等所有音视频格式
编解码学习笔记(一):基本概念 媒体业务是网络的主要业务之间.尤其移动互联网业务的兴起,在运营商和应用开发商中,媒体业务份量极重,其中媒体的编解码服务涉及需求分析.应用开发.释放 license收费等 ...
- 集显也能硬件编码:Intel SDK && 各种音视频编解码学习详解
http://blog.sina.com.cn/s/blog_4155bb1d0100soq9.html INTEL MEDIA SDK是INTEL推出的基于其内建显示核心的编解码技术,我们在播放高清 ...
- 【miscellaneous】各种音视频编解码学习详解
编解码学习笔记(一):基本概念 媒体业务是网络的主要业务之间.尤其移动互联网业务的兴起,在运营商和应用开发商中,媒体业务份量极重,其中媒体的编解码服务涉及需求分析.应用开发.释放license收费等等 ...
- 【FFMPEG】各种音视频编解码学习详解 h264 ,mpeg4 ,aac 等所有音视频格式
目录(?)[-] 编解码学习笔记二codec类型 编解码学习笔记三Mpeg系列Mpeg 1和Mpeg 2 编解码学习笔记四Mpeg系列Mpeg 4 编解码学习笔记五Mpeg系列AAC音频 编解码学习笔 ...
- 了不起的WebRTC:生态日趋完善,或将实时音视频技术白菜化
本文原文由声网WebRTC技术专家毛玉杰分享. 1.前言 有人说 2017 年是 WebRTC 的转折之年,2018 年将是 WebRTC 的爆发之年,这并非没有根据.就在去年(2017年),WebR ...
- 从零到一,使用实时音视频 SDK 一起开发一款 Zoom 吧
zoom(zoom.us) 是一款受到广泛使用的在线会议软件.相信各位一定在办公.会议.聊天等各种场景下体验或者使用过,作为一款成熟的商业软件,zoom 提供了稳定的实时音视频通话质量,以及白板.聊天 ...
- 实时音视频互动系列(下):基于 WebRTC 技术的实战解析
在 WebRTC 项目中,又拍云团队做到了覆盖系统全局,保证项目进程流畅.这牵涉到主要三大块技术点: 网络端.服务端的开发和传输算法 WebRTC 协议中牵扯到服务端的应用协议和信令服务 客户端iOS ...
随机推荐
- 对数据库触发器new和old的理解
在数据库的触发器中经常会用到更新前的值和更新后的值,所有要理解new和old的作用很重要.当时我有个情况是这样的:我要插入一行数据,在行要去其他表中获得一个单价,然后和这行的数据进行相乘的到总金额,将 ...
- “init terminating in do_boot” Windows10 Rabbit MQ fails to start
在Windows 10环境下安装rabbitmq-server-3.6.2后,CMD中运行命令:rabbitmq-plugins enable rabbitmq_management 报错: { , ...
- [荐]Js apply()和call()方法详解 - http://www.w3cfuns.com/article-5596443-1-1.html
本帖最后由 默默DE人生 于 2013-3-19 13:22 编辑 Js apply方法详解我在一开始看到javascript的函数apply和call时,非常的模糊,看也看不懂,最近在网上看到一些文 ...
- 退出Activity(转)
退出Activity 如何退出Activity?如何安全退出已调用多个Activity的Application? 退出activity 直接调用 finish () 方法 . //用户点击back键 ...
- [Liferay6.2]Liferay Dynamic Query API示例
介绍 Liferay提供了几种方法定义复杂的查询用来检索数据库中的数据. 通常情况下,在每个service Entity中,通过定义一些'finder'方法,可以便捷地满足基本的数据查询操作. 但是, ...
- visio 交叉线 不出现拱形怎么办?
- Servlet3.0新特性
1 Servlet3.0新特性概述 使用要求:MyEclipse10.0或以上版本,发布到Tomcat7.0或以上版本,创建JavaEE6.0应用! Servlete3.0的主要新特性如下三部分: 使 ...
- 封装JavaScript的AJAX
// 创建request对象 function createXMLHttpRequest() { try { return new XMLHttpRequest();//大多数浏览器 } catch ...
- mysql注入研究
网址: http://www.jb51.net/article/14446.htm http://www.jb51.net/article/29445.htm
- ce游戏内存修改器(Cheat Engine)
ce修改器(Cheat Engine)一款专门修改内存修改编辑的游戏工具它包括16进制编辑,反汇编程序,内存查找工具新版6.1 版的CE与6.0 最大的区别就是添加了修改器制作工具,比之前 5.6.1 ...