[SRS流媒体服务器]捕捉摄像头的图像后发送到SRS流媒体服务器
NetStream.publish捕捉摄像头的图像,并coded-后发送到:SRS流媒体服务器
NetStream.publish捕捉摄像头的图像,并coded-后发送到:SRS流媒体服务器。闪光灯11终于支持发布H264的流。因为推送H264的流,需要flash播放器能编码H264格式视频,在闪存播放器11加入了H264编码器。
官方参考:
http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/media/H264VideoStreamSettings.html
编写推送h164的作为程序,必须要较高版本的SDK,之前使用的Flex SDK的4.1的flash播放器版本是10.0,不能用来编写这个程序,。
下载的Flex SDK:
http://www.adobe.com/devnet/flex/flex-sdk-download.html
AS3.0代码:
- 包
- {
- 导入 fl.controls.Button;
- 导入 fl.controls.CheckBox;
- 进口 fl.controls.ComboBox;
- 导入 fl.controls.Label;
- 导入 fl.controls.TextInput;
- 导入 flash.display.Sprite;
- 导入 flash.display.StageAlign;
- 进口 flash.display.StageScaleMode;
- 导入 flash.events.Event;
- 导入 flash.events.MouseEvent;
- 导入 flash.events.NetStatusEvent;
- 导入 flash.media.Camera;
- 导入 flash.media.H264Profile;
- 进口 flash.media.H264VideoStreamSettings;
- 导入 flash.media.Microphone;
- 进口 flash.media.Video;
- 导入 flash.net.NetConnection;
- 导入 flash.net.NetStream;
- 公共 类 H264Publisher的 扩展 雪碧
- {
- 公共的 功能 H264Publisher()
- {
- (此阶段== 空){
- this.addEventListener(Event.ADDED_TO_STAGE, this.onAddedToStage);
- }
- 其他{
- 这一点。onAddedToStage(空);
- }
- }
- 的私人的 功能 onAddedToStage(EVT:事件):无效{
- 这stage.align = StageAlign.TOP_LEFT;
- 这Stage.scaleMode的= StageScaleMode.NO_SCALE;
- VAR urlPanel:雪碧= 新 雪碧();
- 本。addUrlPanel(urlPanel,onMouseClickStartPublish,onMouseClickStopPublish);
- VAR cameraPanel:雪碧= 新 雪碧();
- 本。addCameraPanel(cameraPanel);
- VAR encodingPanel:雪碧= 新 雪碧();
- 本。addEncodingPanel(encodingPanel);
- urlPanel.x = 10;
- urlPanel.y = 10;
- cameraPanel.x = urlPanel.x;
- cameraPanel.y = urlPanel.y + 30;
- encodingPanel.x = cameraPanel.x;
- encodingPanel.y = cameraPanel.y + 30;
- 视频= 新 影片();
- video.x = encodingPanel.x;
- video.y = encodingPanel.y + 30;
- 此。的AddChild(urlPanel);
- 此。的AddChild(cameraPanel);
- 此。的AddChild(encodingPanel);
- 此。的AddChild(视频);
- }
- 私人 VAR fmsUrl:字符串;
- 私人 VAR fmsStream:字符串;
- 私人的 功能 discoveryFmsUrl():无效{
- VAR 参数url:String = txtUrl.text;
- 如果(url.toLowerCase()。的indexOf(“RTMP :/ /” )<0){
- 跟踪(“[错误]的URL必须开始与RTMP :/ /” ,“ 错误” );
- 返回;
- }
- / /删除启动RTMP :/ /
- (url.toLowerCase()的indexOf(URL = url.substr “RTMP :/ /” )+ “RTMP :/ /”的长度。);
- VAR 服务器:字符串= url.substr(0,url.indexOf(“/” ));
- 的URL url.substr(url.indexOf的(“/” )+ 1);
- VAR 端口:字符串= “1935” ;
- (server.indexOf( “:” )> = 0){
- 端口= server.substr(server.indexOf( “:” )+1)的;
- 服务器= server.substr(0,server.indexOf( “:” ));
- }
- VAR appIndex:INT = -1;
- ( I: = 0;我< 这个。cbAppLevel.selectedIndex + 1;我+){
- (url.indexOf(“/” ,appIndex + 1)<0){
- 打破;
- }
- appIndex = url.indexOf(“/” ,appIndex + 1);
- }
- VAR 应用程序:字符串= url.substr(,appIndex);
- VAR 流:字符串= url.substr(appIndex + 1);
- / /如果用户输入的IP地址,设置服务器,否则,虚拟主机设置。
- VAR serverIsIPAddress:布尔= TRUE ;
- VAR serverItems:阵列= server.split( “。” );
- (I = 0; <serverItems.length;我+){
- (的isNaN(编号(serverItems [I]))){
- serverIsIPAddress = 虚假的;
- }
- }
- fmsUrl = “RTMP :/ /” +服务器+ “:” +端口+ “/” +应用程序;
- fmsStream =流;
- }
- 私营 功能 buildEncodingParameters(publishStream:NetStream的,C:摄像机,M:麦克风):无效{
- VAR x264profile:字符串=(这cbX264Profile.selectedLabel ==。 “ 主”)?H264Profile.MAIN:H264Profile.BASELINE;
- VAR x264level:字符串= 这cbX264Level.selectedLabel;
- VAR x264KeyFrameInterval:INTINT = INT (此。cbX264KeyFrameInterval.selectedIndex + 1);
- var cameraWidth:int = int(this.cbCameraSize.selectedLabel.substr(0, this.cbCameraSize.selectedLabel.indexOf("x")));
- +1));
- VAR cameraFps:数=(本cbCameraFps.selectedLabel。);
- VAR cameraBitrate:INTINT = INT (。cbCameraBitrate.selectedLabel);
- VAR cameraQuality:INT = 85;
- VAR microEncodeQuality:INT = 8;
- VAR的 microRate:int = 22; / / 22 === 22050赫兹
- 跟踪(“[发布] H.264(X264)编码参数:
- + “个人资料=” + x264profile
- + “级=” + x264level
- + “,keyFrameInterval(GOP)=” + x264KeyFrameInterval
- + “;视频(摄像头)宽=” + cameraWidth
- + “,高度=” + cameraHeight
- + “,FPS =” + cameraFps
- + “,码率=” + cameraBitrate
- + “,质量=” + cameraQuality
- + “;音频(麦克风)encodeQuality的的=” + microEncodeQuality
- + “,率=” + microRate “的(22050Hz的)”
- );
- VAR h264Settings:H264VideoStreamSettings = 新 H264VideoStreamSettings();
- / /我们必须设置其值,然后设置NetStream.videoStreamSettings,它会不断的起源值。
- h264Settings.setProfileLevel“(x264profile x264level);
- publishStream.videoStreamSettings = h264Settings;
- / / setKeyFrameInterval / setMode / setQuality的使用相机设置。
- / /
- / /注意:此功能将在未来版本的Flash Player和AIR的支持下,目前,用于相机参数。
- / * h264Settings.setKeyFrameInterval(4);
- h264Settings.setMode(800,600,15);
- h264Settings.setQuality(500,0)* /;
- / /设置摄像头和麦克风。
- / / setKeyFrameInterval的(keyFrameInterval:INT):无效
- / / keyFrameInterval的:int - 一个值,指定全面传播视频帧(关键帧),而不是被
- / /插入的视频压缩算法。值1表示每帧是关键帧,价值3手段
- / /每三帧是关键帧,依此类推。可接受的值是1到48。
- c.setKeyFrameInterval(x264KeyFrameInterval);
- / / setMode(宽度:INT,高度:INT,FPS:编号,favorArea:布尔=真):无效
- / /宽度:INT - 请求的捕获宽度,以像素为单位。默认值是160。
- / /高度:INT - 请求的捕获高度,以像素为单位。默认值是120。
- / / FPS:编号 - 相机捕捉帧每秒的数据,请求的速率。默认值是15。
- c.setMode的(cameraWidth,cameraHeight,cameraFps);
- / / setQuality的(带宽:INT,质量:INT):无效
- / /带宽:int - 指定的最大带宽量,当前输出视频输入可以使用字节每秒,。
- / /指定的视频可以使用的带宽,需要保持质量的价值,通过对带宽的0。
- / /默认值是16384。
- / /质量:int - 一个整数,指定所需的画面质量水平,如压缩量确定
- / /被应用到每个视频帧。可接受值的范围从1(最低品质,最大压缩)到100
- / /(最高品质,无压缩)。要指定画面质量可以有所不同,以避免超出带宽,
- / /通过质量0。
- / / winlin:
- / /带宽是在BPS不kbps的。500 * 1000 = 500kbps的。
- / /质量= 1是最低的质量,100是最高的质量。
- c.setQuality(cameraBitrate * 1000,cameraQuality);
- / /如果没有麦克风,donot设置的params。
- 如果(M == 空){
- 返回;
- }
- / /使用Speex编解码器时,编码的语音质量。可能的值是从0到10。默认值是6。较高的数字
- / /代表更高的质量,但需要更多的带宽,如下表所示。所列出的比特率值代表
- / /净比特率,不包括打包开销。
- m.encodeQuality = microEncodeQuality;
- / /麦克风捕捉声音千赫,利率。可接受的值是5,8,11,22和44。默认值是8 kHz
- / /如果您的声音捕获设备支持此值。否则,默认值是高于8 kHz下一个可用捕获级别
- / /你的声音捕获设备支持,通常为11 kHz。
- m.rate = microRate;
- }
- 私人的 VAR publishStream:NetStream的;
- 私人的 VAR publishConnection:NetConnection对象;
- 私营 功能 onMouseClickStartPublish(EVT:为MouseEvent):无效{
- / /如果出版,donothing
- (publishStream!= 空){
- 返回;
- }
- 这btnStartPublish.enabled =。 假;
- 这btnStopPublish.enabled =。 真实;
- 本的。discoveryFmsUrl();
- publishConnection = 新 的NetConnection();
- VAR 列出的NetConnection = publishConnection;
- conn.client = {};
- conn.client.onBWDone = 函数():无效{};
- conn.addEventListener(NetStatusEvent.NET_STATUS, 功能(EVT:NetStatusEvent):无效{
- 跟踪(“[发布] [连接]的代码:” + evt.info.code);
- 开关(evt.info.code){
- 案 “NetConnection.Connect.Success” :
- publishStream = 新 的NetStream(CONN);
- / /麦克风和摄像头
- VAR M:麦克风= Microphone.getMicrophone(cbMicrophone.selectedIndex);
- / /注:该名称是该指数!
- VAR C:相机= Camera.getCamera(字符串(cbCamera.selectedIndex)的);
- (C == 空){
- 跟踪(“[发布] [错误]无法打开相机(名称=” +字符串(cbCamera.selectedIndex)+ ):“ + cbCamera.selectedLabel, “ 错误” );
- cleanupPublishedStream();
- 打破;
- }
- 否则, 如果(c.muted){
- 跟踪(“[发布] [错误]打开相机(名称=” +字符串(cbCamera.selectedIndex)+ “)失败,这是静音:” + cbCamera.selectedLabel, “ 错误” );
- cleanupPublishedStream();
- 打破;
- }
- buildEncodingParameters(publishStream,C,M);
- publishStream.addEventListener(NetStatusEvent.NET_STATUS, 功能(EVT:NetStatusEvent):无效{
- 跟踪(“[发布] [NetStreamStatus]” + evt.info.code);
- 开关(evt.info.code){
- 案 “NetStream.Publish.Start” :
- VAR H264:H264VideoStreamSettings =作为H264VideoStreamSettings的publishStream.videoStreamSettings;
- 跟踪(“[发布]视频编解码器:” + h264.codec
- + “,个人资料=” + h264.profile
- + “级=” + h264.level
- + “,质量=” + h264.quality
- + “,FPS =” + h264.fps
- + “,GOP =” + h264.keyFrameInterval
- + “,带宽=” + h264.bandwidth
- + “,大小=” + h264.width + “X” + h264.height);
- 打破;
- 情况 :
- cleanupPublishedStream();
- 打破;
- }
- });
- publishStream.publish(fmsStream);
- / /将视频和音频。
- 跟踪(“[发布] [调试]开始发布,使用摄像头(名称=” +字符串(cbCamera.selectedIndex)+ ):“ + c.name);
- publishStream.attachCamera(C);
- (M = 空 && m.muted的){
- 跟踪(“[发布] [调试]开始发布,使用麦克风(名称=” +字符串(cbMicrophone.selectedIndex)+ “):” + m.name);
- publishStream.attachAudio(米);
- }
- restartPlayback();
- 打破;
- 案 “NetConnection.Connect.Rejected” :
- 案 “NetConnection.Connect.Failed的” :
- cleanupPublishedStream();
- 打破;
- }
- });
- conn.connect(fmsUrl);
- }
- 私人的 功能 cleanupPublishedStream():无效{
- 这btnStartPublish.enabled =。 真实;
- 这btnStopPublish.enabled =。 假;
- (此。publishStream!= 空){
- 本的。publishStream.close();
- }
- (此。publishConnection!= 空){
- 本的。publishConnection.close();
- }
- 这publishStream =。 空;
- }
- 公共的 VAR 流:NetStream的;
- 私人 VAR CONN:NetConnection对象;
- 私人的 VAR 视频:视频;
- 私人 功能 restartPlayback():无效{
- / /流播放,恢复它。
- (此。流!= 空){
- 本的。stream.close();
- }
- CONN = 新 的NetConnection();
- conn.client = {};
- conn.client.onBWDone = 函数():无效{};
- conn.addEventListener(NetStatusEvent.NET_STATUS, 功能(EVT:NetStatusEvent):无效{
- 跟踪(“[连接]代码:” + evt.info.code + “DESC:” + evt.info.description);
- 开关(evt.info.code){
- 案 “NetConnection.Connect.Success” :
- = 新 的NetStream流 (CONN);
- video.attachNetStream(流);
- / / stream.bufferTime = 3;
- stream.addEventListener(NetStatusEvent.NET_STATUS, 功能(EVT:NetStatusEvent):无效{
- 跟踪(“[NetStreamStatus]” + evt.info.code + “DESC:” + evt.info.description);
- });
- stream.client = {};
- stream.client.onMetaData, 功能 onMetadata(元数据对象):{
- VAR O:对象= {};
- (VAR 关键:字符串 中 的元数据){
- Ø[关键] =元数据[关键];
- 跟踪(“元数据” + “键 + “值=“ +键 “ + O [关键]);
- }
- (metadata.width ==未定义){
- metadata.width = 10;
- 跟踪(“[警告] metadata.width undefied,设置为10” );
- }
- (metadata.height ==未定义){
- metadata.height = 10;
- 跟踪(“[警告] metadata.height undefied,设置为10” );
- }
- video.width = metadata.width;
- video.height = metadata.height;
- };
- 如果(cbIsLive.selected){
- stream.play(fmsStream,0);
- }
- 其他{
- stream.play(fmsStream);
- }
- 打破;
- 案 “NetConnection.Connect.Rejected” :
- 案 “NetConnection.Connect.Failed的” :
- stream.close();
- 流= 空;
- 打破;
- }
- });
- conn.connect(fmsUrl);
- }
- 私营 功能 onMouseClickStopPublish(EVT:为MouseEvent):无效{
- 本的。cleanupPublishedStream();
- }
- 私人 VAR txtUrl:TextInput的;
- 私人的 VAR btnStartPublish:按钮;
- 私人的 VAR btnStopPublish:按钮;
- 私人 VAR cbAppLevel:ComboBox的;
- 私人 VAR cbIsLive:CheckBox的;
- 私营 功能 addUrlPanel的(
- 面板:雪碧,
- 的onMouseClickStartPublish:功能,onMouseClickStopPublish的功能
- ):无效{
- VAR lblUrl:标签 新 标签();
- lblUrl.text = “RTMP URL:” ;
- lblUrl.width = 50;
- panel.addChild(lblUrl);
- txtUrl = 新 的TextInput();
- txtUrl.width = 380;
- txtUrl.x = lblUrl.x + lblUrl.width + 3;
- panel.addChild(txtUrl);
- cbIsLive = 新 的CheckBox();
- cbIsLive.selected = 真;
- cbIsLive.label = “ 活” ;
- cbIsLive.width = 53;
- cbIsLive.x = txtUrl.x + txtUrl.width + 0;
- panel.addChild(cbIsLive);
- cbAppLevel = 新 组合框();
- cbAppLevel.addItem({标签: “1级应用” });
- cbAppLevel.addItem({标签: “2级应用” });
- cbAppLevel.addItem({标签: “3级应用” });
- cbAppLevel.addItem({标签: “4级应用” });
- cbAppLevel.width = 70;
- cbAppLevel.x = cbIsLive.x + cbIsLive.width + 0;
- panel.addChild(cbAppLevel);
- btnStartPublish = 新 按钮();
- btnStartPublish.label = “ 发布流” ;
- btnStartPublish.width = 60;
- btnStartPublish.x = cbAppLevel.x + cbAppLevel.width + 3;
- btnStartPublish.addEventListener(MouseEvent.CLICK,onMouseClickStartPublish)的;
- panel.addChild(btnStartPublish);
- btnStopPublish = 新 按钮();
- btnStopPublish.label = “ 停止发布” ;
- btnStopPublish.width = 60;
- btnStopPublish.enabled = 假
- btnStopPublish.x = btnStartPublish.x + btnStartPublish.width + 3;
- btnStopPublish.addEventListener(MouseEvent.CLICK,onMouseClickStopPublish)的;
- panel.addChild(btnStopPublish);
- }
- 私人的 VAR cbX264Profile:ComboBox的;
- 私人 VAR cbX264Level:ComboBox的;
- 私人的 VAR cbX264KeyFrameInterval:ComboBox的;
- 私人的 VAR cbCameraSize:ComboBox的;
- 私人的 VAR cbCameraFps:ComboBox的;
- 私人的 VAR cbCameraBitrate:ComboBox的;
- 私营 功能 addEncodingPanel的(
- 面板:雪碧
- ):无效{
- VAR lblX264Profile:标签 新 标签();
- lblX264Profile.text = “简介:” ;
- lblX264Profile.width = 38;
- lblX264Profile.y = 2;
- panel.addChild(lblX264Profile);
- cbX264Profile = 新 的ComboBox();
- cbX264Profile.width = 72;
- cbX264Profile.x = lblX264Profile.x + lblX264Profile.width + 0;
- panel.addChild(cbX264Profile);
- cbX264Profile.addItem({标签:“基准” });
- cbX264Profile.addItem({标签:“主” });
- VAR lblX264Level:标签 新 标签();
- lblX264Level.text = “等级:” ;
- lblX264Level.width = 32;
- lblX264Level.y = 2;
- lblX264Level.x = cbX264Profile.x + cbX264Profile.width + 1;
- panel.addChild(lblX264Level);
- cbX264Level = 新 组合框();
- cbX264Level.width = 45;
- cbX264Level.x = lblX264Level.x + lblX264Level.width + 1;
- panel.addChild(cbX264Level);
- VAR x264Levels:阵列= [ “1” , “1B” , “1.1” , “1.2” , “1.3” , “2” , “2.1” , “2.2” , “3” , “3.1” , “3.2” , “4” , “4.1” “4.2” , “5” , “5.1” ];
- ( I: = 0;我<x264Levels.length;我+){
- cbX264Level.addItem({标签:x264Levels [I]});
- }
- cbX264Level.selectedIndex = 8;
- VAR lblX264KeyFrameInterval:标签 新 标签();
- lblX264KeyFrameInterval.text = “共和党” ;
- lblX264KeyFrameInterval.width = 29;
- lblX264KeyFrameInterval.y = 2;
- lblX264KeyFrameInterval.x = cbX264Level.x + cbX264Level.width + 1;
- panel.addChild(lblX264KeyFrameInterval);
- cbX264KeyFrameInterval = 新 的ComboBox();
- cbX264KeyFrameInterval.width = 87;
- cbX264KeyFrameInterval.x = lblX264KeyFrameInterval.x + lblX264KeyFrameInterval.width + 1;
- panel.addChild(cbX264KeyFrameInterval);
- (I = 0; I <48; I + +){
- cbX264KeyFrameInterval.addItem({标签:字符串(I + 1)+ “秒” });
- }
- cbX264KeyFrameInterval.selectedIndex = 3;
- VAR lblCameraSize:标签 新 标签();
- lblCameraSize.text = “大小:” ;
- lblCameraSize.width = 30;
- lblCameraSize.y = 2;
- lblCameraSize.x = cbX264KeyFrameInterval.x + cbX264KeyFrameInterval.width + 1;
- panel.addChild(lblCameraSize);
- cbCameraSize = 新 的ComboBox();
- cbCameraSize.width = 82;
- cbCameraSize.x = lblCameraSize.x + lblCameraSize.width + 1;
- panel.addChild(cbCameraSize);
- VAR 大小:阵列=
- (I = 0; <sizes.length;我+){
- cbCameraSize.addItem({标签:大小[I]});
- }
- cbCameraSize.selectedIndex = 1;
- VAR lblCameraFps:标签= 新 标签();
- lblCameraFps.text = “的FPS:” ;
- lblCameraFps.width = 28;
- lblCameraFps.y = 2;
- lblCameraFps.x = cbCameraSize.x + cbCameraSize.width + 1;
- panel.addChild(lblCameraFps);
- cbCameraFps = 新 组合框();
- cbCameraFps.width = 58;
- cbCameraFps.x = lblCameraFps.x + lblCameraFps.width + 1;
- panel.addChild(cbCameraFps);
- VAR fpses:阵列=
- (I = 0; <fpses.length;我+){
- cbCameraFps.addItem({标签:fpses [I]});
- }
- cbCameraFps.selectedIndex = 8;
- VAR lblCameraBitrate:标签 新 标签();
- lblCameraBitrate.text = “比特率” ;
- lblCameraBitrate.width = 40;
- lblCameraBitrate.y = 2;
- lblCameraBitrate.x = cbCameraFps.x + cbCameraFps.width + 1;
- panel.addChild(lblCameraBitrate);
- cbCameraBitrate = 新 的ComboBox();
- cbCameraBitrate.width = 58;
- cbCameraBitrate.x = lblCameraBitrate.x + lblCameraBitrate.width + 1;
- panel.addChild(cbCameraBitrate);
- VAR 比特率:阵列=
- (I = 0; <bitrates.length;我+){
- cbCameraBitrate.addItem({标签:比特率[I]});
- }
- cbCameraBitrate.selectedIndex = 3;
- }
- 私人的 VAR cbCamera:ComboBox的;
- 私人的 VAR cbMicrophone:ComboBox的;
- 私营 功能 addCameraPanel的(
- 面板:雪碧
- ):无效{
- / /摄像头
- VAR lblCamera:标签 新 标签();
- lblCamera.text = “可用的摄像头:” ;
- lblCamera.width = 100;
- panel.addChild(lblCamera);
- cbCamera = 新 组合框();
- cbCamera.width = 160;
- cbCamera.x = lblCamera.x + lblCamera.width + 3;
- panel.addChild(cbCamera);
- VAR 相机:阵列= Camera.names;
- ( I: = 0;我<cameras.length;我+){
- cbCamera.addItem({标签:相机[I]});
- }
- / /麦克风
- VAR lblMicrophone:标签 新 标签();
- lblMicrophone.text = “可用的麦克风:” ;
- lblMicrophone.width = 120;
- lblMicrophone.x = cbCamera.x + cbCamera.width + 10;
- panel.addChild(lblMicrophone);
- cbMicrophone = 新 组合框();
- cbMicrophone.width = 180;
- cbMicrophone.x = lblMicrophone.x + lblMicrophone.width + 3;
- panel.addChild(cbMicrophone);
- VAR 麦克风:阵列= Microphone.names;
- (I = 0; <microphones.length;我+){
- cbMicrophone.addItem({标签:麦克风[I]});
- }
- }
- }
- }
热门文章推荐
- [SRS流媒体]SRS rtmp http-flv流低延时设置、测试
- [SRS流媒体]RTMP部署的步骤
- [SRS流媒体]RTMP/HLS 直播服务器simple-rtmp-server安装
- [SRS]srs流媒体RTMP环境配置(RTMP配置教程)
- [SRS流媒体]Simple Rtmp Server的安装与简单使用
- [SRS流媒体]SRS集群边缘节点配置
- [SRS流媒体服务器]捕捉摄像头的图像后发送到SRS流媒体服务器
- [srs流媒体技术]Simple-RTMP-Server流媒体
请稍候...