flash actionscript 3.0 publish h264 stream
来源:互联网 发布:淘宝上的打折邮票真假 编辑:程序博客网 时间:2024/05/13 22:58
NetStream.publish捕捉摄像头的图像,并编码后发送到FMS服务器。flash 11终于支持发布h264的流。因为推送h264的流,需要flash player能编码h264格式视频,在flash player 11加入了h264编码器。
官方参考:
http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/media/H264VideoStreamSettings.html
编写推送h164的as程序必须要较高版本的sdk,之前使用的flex sdk 4.1的flash player版本是10.0,不能用来编写这个程序。
下载flex sdk:
http://www.adobe.com/devnet/flex/flex-sdk-download.html
h264和h263对比图(同样的码率和分辨率):
as3.0代码:
- package
- {
- import fl.controls.Button;
- import fl.controls.CheckBox;
- import fl.controls.ComboBox;
- import fl.controls.Label;
- import fl.controls.TextInput;
- import flash.display.Sprite;
- import flash.display.StageAlign;
- import flash.display.StageScaleMode;
- import flash.events.Event;
- import flash.events.MouseEvent;
- import flash.events.NetStatusEvent;
- import flash.media.Camera;
- import flash.media.H264Profile;
- import flash.media.H264VideoStreamSettings;
- import flash.media.Microphone;
- import flash.media.Video;
- import flash.net.NetConnection;
- import flash.net.NetStream;
- public class H264Publisher extends Sprite
- {
- public function H264Publisher()
- {
- if(this.stage == null){
- this.addEventListener(Event.ADDED_TO_STAGE, this.onAddedToStage);
- }
- else{
- this.onAddedToStage(null);
- }
- }
- private function onAddedToStage(evt:Event):void{
- this.stage.align = StageAlign.TOP_LEFT;
- this.stage.scaleMode = StageScaleMode.NO_SCALE;
- var urlPanel:Sprite = new Sprite();
- this.addUrlPanel(urlPanel, onMouseClickStartPublish, onMouseClickStopPublish);
- var cameraPanel:Sprite = new Sprite();
- this.addCameraPanel(cameraPanel);
- var encodingPanel:Sprite = new Sprite();
- this.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 = new Video();
- video.x = encodingPanel.x;
- video.y = encodingPanel.y + 30;
- this.addChild(urlPanel);
- this.addChild(cameraPanel);
- this.addChild(encodingPanel);
- this.addChild(video);
- }
- private var fmsUrl:String;
- private var fmsStream:String;
- private function discoveryFmsUrl():void{
- var url:String = txtUrl.text;
- if(url.toLowerCase().indexOf("rtmp://") < 0){
- trace("[error] the url must start with rtmp://", "error");
- return;
- }
- // remove the start rtmp://
- url = url.substr(url.toLowerCase().indexOf("rtmp://") + "rtmp://".length);
- var server:String = url.substr(0, url.indexOf("/"));
- url = url.substr(url.indexOf("/") + 1);
- var port:String = "1935";
- if(server.indexOf(":") >= 0){
- port = server.substr(server.indexOf(":")+1);
- server = server.substr(0, server.indexOf(":"));
- }
- var appIndex:int = -1;
- for(var i:int = 0; i < this.cbAppLevel.selectedIndex + 1; i++){
- if(url.indexOf("/", appIndex + 1) < 0){
- break;
- }
- appIndex = url.indexOf("/", appIndex + 1);
- }
- var app:String = url.substr(0, appIndex);
- var stream:String = url.substr(appIndex + 1);
- // if user input ip address, set the server; otherwise, set the vhost.
- var serverIsIPAddress:Boolean = true;
- var serverItems:Array = server.split(".");
- for(i = 0; i < serverItems.length; i++){
- if(isNaN(Number(serverItems[i]))){
- serverIsIPAddress = false;
- }
- }
- fmsUrl = "rtmp://" + server + ":" + port + "/" + app;
- fmsStream = stream;
- }
- private function buildEncodingParameters(publishStream:NetStream, c:Camera, m:Microphone):void{
- var x264profile:String = (this.cbX264Profile.selectedLabel == "Main") ? H264Profile.MAIN : H264Profile.BASELINE;
- var x264level:String = this.cbX264Level.selectedLabel;
- var x264KeyFrameInterval:int = int(this.cbX264KeyFrameInterval.selectedIndex + 1);
- var cameraWidth:int = int(this.cbCameraSize.selectedLabel.substr(0, this.cbCameraSize.selectedLabel.indexOf("x")));
- var cameraHeight:int = int(this.cbCameraSize.selectedLabel.substr(this.cbCameraSize.selectedLabel.indexOf("x") + 1));;
- var cameraFps:Number = Number(this.cbCameraFps.selectedLabel);
- var cameraBitrate:int = int(this.cbCameraBitrate.selectedLabel);
- var cameraQuality:int = 85;
- var microEncodeQuality:int = 8;
- var microRate:int = 22; // 22 === 22050 Hz
- trace("[Publish] h.264(x264) encoding parameters: "
- + "profile=" + x264profile
- + ", level=" + x264level
- + ", keyFrameInterval(gop)=" + x264KeyFrameInterval
- + "; video(camera) width=" + cameraWidth
- + ", height=" + cameraHeight
- + ", fps=" + cameraFps
- + ", bitrate=" + cameraBitrate
- + ", quality=" + cameraQuality
- + "; audio(microphone) encodeQuality=" + microEncodeQuality
- + ", rate=" + microRate + "(22050Hz)"
- );
- var h264Settings:H264VideoStreamSettings = new H264VideoStreamSettings();
- // we MUST set its values first, then set the NetStream.videoStreamSettings, or it will keep the origin values.
- h264Settings.setProfileLevel(x264profile, x264level);
- publishStream.videoStreamSettings = h264Settings;
- // the setKeyFrameInterval/setMode/setQuality use the camera settings.
- // http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/media/VideoStreamSettings.html
- // Note This feature will be supported in future releases of Flash Player and AIR, for now, Camera parameters are used.
- /*h264Settings.setKeyFrameInterval(4);
- h264Settings.setMode(800, 600, 15);
- h264Settings.setQuality(500, 0);*/
- // set the camera and microphone.
- // setKeyFrameInterval(keyFrameInterval:int):void
- // keyFrameInterval:int — A value that specifies which video frames are transmitted in full (as keyframes) instead of being
- // interpolated by the video compression algorithm. A value of 1 means that every frame is a keyframe, a value of 3 means
- // that every third frame is a keyframe, and so on. Acceptable values are 1 through 48.
- c.setKeyFrameInterval(x264KeyFrameInterval);
- // setMode(width:int, height:int, fps:Number, favorArea:Boolean = true):void
- // width:int — The requested capture width, in pixels. The default value is 160.
- // height:int — The requested capture height, in pixels. The default value is 120.
- // fps:Number — The requested rate at which the camera should capture data, in frames per second. The default value is 15.
- c.setMode(cameraWidth, cameraHeight, cameraFps);
- // setQuality(bandwidth:int, quality:int):void
- // bandwidth:int — Specifies the maximum amount of bandwidth that the current outgoing video feed can use, in bytes per second.
- // To specify that the video can use as much bandwidth as needed to maintain the value of quality, pass 0 for bandwidth.
- // The default value is 16384.
- // quality:int — An integer that specifies the required level of picture quality, as determined by the amount of compression
- // being applied to each video frame. Acceptable values range from 1 (lowest quality, maximum compression) to 100
- // (highest quality, no compression). To specify that picture quality can vary as needed to avoid exceeding bandwidth,
- // pass 0 for quality.
- // winlin:
- // bandwidth is in bps not kbps. 500*1000 = 500kbps.
- // quality=1 is lowest quality, 100 is highest quality.
- c.setQuality(cameraBitrate * 1000, cameraQuality);
- // if no microphone, donot set the params.
- if(m == null){
- return;
- }
- // The encoded speech quality when using the Speex codec. Possible values are from 0 to 10. The default value is 6. Higher numbers
- // represent higher quality but require more bandwidth, as shown in the following table. The bit rate values that are listed represent
- // net bit rates and do not include packetization overhead.
- m.encodeQuality = microEncodeQuality;
- // The rate at which the microphone is capturing sound, in kHz. Acceptable values are 5, 8, 11, 22, and 44. The default value is 8 kHz
- // if your sound capture device supports this value. Otherwise, the default value is the next available capture level above 8 kHz that
- // your sound capture device supports, usually 11 kHz.
- m.rate = microRate;
- }
- private var publishStream:NetStream;
- private var publishConnection:NetConnection;
- private function onMouseClickStartPublish(evt:MouseEvent):void{
- // if published, donothing
- if(publishStream != null){
- return;
- }
- this.btnStartPublish.enabled = false;
- this.btnStopPublish.enabled = true;
- this.discoveryFmsUrl();
- publishConnection = new NetConnection();
- var conn:NetConnection = publishConnection;
- conn.client = {};
- conn.client.onBWDone = function():void{};
- conn.addEventListener(NetStatusEvent.NET_STATUS, function(evt:NetStatusEvent):void{
- trace("[Publish][connection] code:" + evt.info.code);
- switch(evt.info.code){
- case "NetConnection.Connect.Success":
- publishStream = new NetStream(conn);
- // microphone and camera
- var m:Microphone = Microphone.getMicrophone(cbMicrophone.selectedIndex);
- // Remark: the name is the index!
- var c:Camera = Camera.getCamera(String(cbCamera.selectedIndex));
- if(c == null){
- trace("[Publish][error] failed to open camera(name=" + String(cbCamera.selectedIndex) + "): " + cbCamera.selectedLabel, "error");
- cleanupPublishedStream();
- break;
- }
- else if(c.muted){
- trace("[Publish][error] open camera(name=" + String(cbCamera.selectedIndex) + ") failed, it's muted: " + cbCamera.selectedLabel, "error");
- cleanupPublishedStream();
- break;
- }
- buildEncodingParameters(publishStream, c, m);
- publishStream.addEventListener(NetStatusEvent.NET_STATUS, function(evt:NetStatusEvent):void{
- trace("[Publish][NetStreamStatus]" + evt.info.code);
- switch(evt.info.code){
- case "NetStream.Publish.Start":
- var h264:H264VideoStreamSettings = publishStream.videoStreamSettings as H264VideoStreamSettings;
- trace("[Publish] video codec: " + h264.codec
- + ", profile=" + h264.profile
- + ", level=" + h264.level
- + ", quality=" + h264.quality
- + ", fps=" + h264.fps
- + ", gop=" + h264.keyFrameInterval
- + ", bandwidth=" + h264.bandwidth
- + ", size=" + h264.width + "x" + h264.height);
- break;
- case "NetStream.Publish.BadName":
- cleanupPublishedStream();
- break;
- }
- });
- publishStream.publish(fmsStream);
- // attach video and audio.
- trace("[Publish][debug] start publish, using camera(name=" + String(cbCamera.selectedIndex) + "): " + c.name);
- publishStream.attachCamera(c);
- if(m != null && !m.muted){
- trace("[Publish][debug] start publish, using microphone(name=" + String(cbMicrophone.selectedIndex) + "): " + m.name);
- publishStream.attachAudio(m);
- }
- restartPlayback();
- break;
- case "NetConnection.Connect.Rejected":
- case "NetConnection.Connect.Failed":
- cleanupPublishedStream();
- break;
- }
- });
- conn.connect(fmsUrl);
- }
- private function cleanupPublishedStream():void{
- this.btnStartPublish.enabled = true;
- this.btnStopPublish.enabled = false;
- if(this.publishStream != null){
- this.publishStream.close();
- }
- if(this.publishConnection != null){
- this.publishConnection.close();
- }
- this.publishStream = null;
- }
- public var stream:NetStream;
- private var conn:NetConnection;
- private var video:Video;
- private function restartPlayback():void{
- // stream is playing, resume it.
- if(this.stream != null){
- this.stream.close();
- }
- conn = new NetConnection();
- conn.client = {};
- conn.client.onBWDone = function():void{};
- conn.addEventListener(NetStatusEvent.NET_STATUS, function(evt:NetStatusEvent):void{
- trace("[connection] code:" + evt.info.code + " desc:" + evt.info.description);
- switch(evt.info.code){
- case "NetConnection.Connect.Success":
- stream = new NetStream(conn);
- video.attachNetStream(stream);
- //stream.bufferTime = 3;
- stream.addEventListener(NetStatusEvent.NET_STATUS, function(evt:NetStatusEvent):void{
- trace("[NetStreamStatus]" + evt.info.code + " desc:" + evt.info.description);
- });
- stream.client = {};
- stream.client.onMetaData = function onMetadata(metadata:Object):void{
- var o:Object = {};
- for(var key:String in metadata){
- o[key] = metadata[key];
- trace("[metadata] " + "key=" + key + ", value=" + o[key]);
- }
- if(metadata.width == undefined){
- metadata.width = 10;
- trace("[warning] metadata.width is undefied, set to 10");
- }
- if(metadata.height == undefined){
- metadata.height = 10;
- trace("[warning] metadata.height is undefied, set to 10");
- }
- video.width = metadata.width;
- video.height = metadata.height;
- };
- if(!cbIsLive.selected){
- stream.play(fmsStream, 0);
- }
- else{
- stream.play(fmsStream);
- }
- break;
- case "NetConnection.Connect.Rejected":
- case "NetConnection.Connect.Failed":
- stream.close();
- stream = null;
- break;
- }
- });
- conn.connect(fmsUrl);
- }
- private function onMouseClickStopPublish(evt:MouseEvent):void{
- this.cleanupPublishedStream();
- }
- private var txtUrl:TextInput;
- private var btnStartPublish:Button;
- private var btnStopPublish:Button;
- private var cbAppLevel:ComboBox;
- private var cbIsLive:CheckBox;
- private function addUrlPanel(
- panel:Sprite,
- onMouseClickStartPublish:Function, onMouseClickStopPublish:Function
- ):void{
- var lblUrl:Label = new Label();
- lblUrl.text = "RTMP Url:";
- lblUrl.width = 50;
- panel.addChild(lblUrl);
- txtUrl = new TextInput();
- txtUrl.width = 380;
- txtUrl.x = lblUrl.x + lblUrl.width + 3;
- panel.addChild(txtUrl);
- cbIsLive = new CheckBox();
- cbIsLive.selected = true;
- cbIsLive.label = "Live";
- cbIsLive.width = 53;
- cbIsLive.x = txtUrl.x + txtUrl.width + 0;
- panel.addChild(cbIsLive);
- cbAppLevel = new ComboBox();
- cbAppLevel.addItem({label: "1级App"});
- cbAppLevel.addItem({label: "2级App"});
- cbAppLevel.addItem({label: "3级App"});
- cbAppLevel.addItem({label: "4级App"});
- cbAppLevel.width = 70;
- cbAppLevel.x = cbIsLive.x + cbIsLive.width + 0;
- panel.addChild(cbAppLevel);
- btnStartPublish = new Button();
- btnStartPublish.label = "发布流";
- btnStartPublish.width = 60;
- btnStartPublish.x = cbAppLevel.x + cbAppLevel.width + 3;
- btnStartPublish.addEventListener(MouseEvent.CLICK, onMouseClickStartPublish);
- panel.addChild(btnStartPublish);
- btnStopPublish = new Button();
- btnStopPublish.label = "停止发布";
- btnStopPublish.width = 60;
- btnStopPublish.enabled = false;
- btnStopPublish.x = btnStartPublish.x + btnStartPublish.width + 3;
- btnStopPublish.addEventListener(MouseEvent.CLICK, onMouseClickStopPublish);
- panel.addChild(btnStopPublish);
- }
- private var cbX264Profile:ComboBox;
- private var cbX264Level:ComboBox;
- private var cbX264KeyFrameInterval:ComboBox;
- private var cbCameraSize:ComboBox;
- private var cbCameraFps:ComboBox;
- private var cbCameraBitrate:ComboBox;
- private function addEncodingPanel(
- panel:Sprite
- ):void{
- var lblX264Profile:Label = new Label();
- lblX264Profile.text = "Profile:";
- lblX264Profile.width = 38;
- lblX264Profile.y = 2;
- panel.addChild(lblX264Profile);
- cbX264Profile = new ComboBox();
- cbX264Profile.width = 72;
- cbX264Profile.x = lblX264Profile.x + lblX264Profile.width + 0;
- panel.addChild(cbX264Profile);
- cbX264Profile.addItem({label:"Baseline"});
- cbX264Profile.addItem({label:"Main"});
- var lblX264Level:Label = new Label();
- lblX264Level.text = "Level:";
- lblX264Level.width = 32;
- lblX264Level.y = 2;
- lblX264Level.x = cbX264Profile.x + cbX264Profile.width + 1;
- panel.addChild(lblX264Level);
- cbX264Level = new ComboBox();
- cbX264Level.width = 45;
- cbX264Level.x = lblX264Level.x + lblX264Level.width + 1;
- panel.addChild(cbX264Level);
- var x264Levels:Array = ["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"];
- for(var i:int = 0; i < x264Levels.length; i++){
- cbX264Level.addItem({label:x264Levels[i]});
- }
- cbX264Level.selectedIndex = 8;
- var lblX264KeyFrameInterval:Label = new Label();
- lblX264KeyFrameInterval.text = "GOP:";
- lblX264KeyFrameInterval.width = 29;
- lblX264KeyFrameInterval.y = 2;
- lblX264KeyFrameInterval.x = cbX264Level.x + cbX264Level.width + 1;
- panel.addChild(lblX264KeyFrameInterval);
- cbX264KeyFrameInterval = new ComboBox();
- cbX264KeyFrameInterval.width = 87;
- cbX264KeyFrameInterval.x = lblX264KeyFrameInterval.x + lblX264KeyFrameInterval.width + 1;
- panel.addChild(cbX264KeyFrameInterval);
- for(i = 0; i < 48; i++){
- cbX264KeyFrameInterval.addItem({label:String(i + 1) + " seconds"});
- }
- cbX264KeyFrameInterval.selectedIndex = 3;
- var lblCameraSize:Label = new Label();
- lblCameraSize.text = "Size:";
- lblCameraSize.width = 30;
- lblCameraSize.y = 2;
- lblCameraSize.x = cbX264KeyFrameInterval.x + cbX264KeyFrameInterval.width + 1;
- panel.addChild(lblCameraSize);
- cbCameraSize = new ComboBox();
- cbCameraSize.width = 82;
- cbCameraSize.x = lblCameraSize.x + lblCameraSize.width + 1;
- panel.addChild(cbCameraSize);
- var sizes:Array = ["176x144", "320x240", "352x240", "352x288", "640x480", "720x480", "720x576", "800x600", "1024x768", "1280x720", "1360x768", "1920x1080"];
- for(i = 0; i < sizes.length; i++){
- cbCameraSize.addItem({label:sizes[i]});
- }
- cbCameraSize.selectedIndex = 1;
- var lblCameraFps:Label = new Label();
- lblCameraFps.text = "FPS:";
- lblCameraFps.width = 28;
- lblCameraFps.y = 2;
- lblCameraFps.x = cbCameraSize.x + cbCameraSize.width + 1;
- panel.addChild(lblCameraFps);
- cbCameraFps = new ComboBox();
- cbCameraFps.width = 58;
- cbCameraFps.x = lblCameraFps.x + lblCameraFps.width + 1;
- panel.addChild(cbCameraFps);
- var fpses:Array = ["1.00", "4.00", "5.00", "6.00", "8.00", "10.00", "12.00", "14.98", "15.00", "20.00", "24.00", "25.00", "29.97", "30.00", "59.94", "60.00"];
- for(i = 0; i < fpses.length; i++){
- cbCameraFps.addItem({label:fpses[i]});
- }
- cbCameraFps.selectedIndex = 8;
- var lblCameraBitrate:Label = new Label();
- lblCameraBitrate.text = "Bitrate:";
- lblCameraBitrate.width = 40;
- lblCameraBitrate.y = 2;
- lblCameraBitrate.x = cbCameraFps.x + cbCameraFps.width + 1;
- panel.addChild(lblCameraBitrate);
- cbCameraBitrate = new ComboBox();
- cbCameraBitrate.width = 58;
- cbCameraBitrate.x = lblCameraBitrate.x + lblCameraBitrate.width + 1;
- panel.addChild(cbCameraBitrate);
- var bitrates:Array = ["10", "50", "100", "200", "350", "500", "650", "800", "950", "1000", "1200", "1500", "1800", "2000", "2500", "20000"];
- for(i = 0; i < bitrates.length; i++){
- cbCameraBitrate.addItem({label:bitrates[i]});
- }
- cbCameraBitrate.selectedIndex = 3;
- }
- private var cbCamera:ComboBox;
- private var cbMicrophone:ComboBox;
- private function addCameraPanel(
- panel:Sprite
- ):void{
- // camera
- var lblCamera:Label = new Label();
- lblCamera.text = "Available Cameras:";
- lblCamera.width = 100;
- panel.addChild(lblCamera);
- cbCamera = new ComboBox();
- cbCamera.width = 160;
- cbCamera.x = lblCamera.x + lblCamera.width + 3;
- panel.addChild(cbCamera);
- var cameras:Array = Camera.names;
- for(var i:int = 0; i < cameras.length; i++){
- cbCamera.addItem({label:cameras[i]});
- }
- // microphone
- var lblMicrophone:Label = new Label();
- lblMicrophone.text = "Available Microphones:";
- lblMicrophone.width = 120;
- lblMicrophone.x = cbCamera.x + cbCamera.width + 10;
- panel.addChild(lblMicrophone);
- cbMicrophone = new ComboBox();
- cbMicrophone.width = 180;
- cbMicrophone.x = lblMicrophone.x + lblMicrophone.width + 3;
- panel.addChild(cbMicrophone);
- var microphones:Array = Microphone.names;
- for(i = 0; i < microphones.length; i++){
- cbMicrophone.addItem({label:microphones[i]});
- }
- }
- }
- }
package{import fl.controls.Button;import fl.controls.CheckBox;import fl.controls.ComboBox;import fl.controls.Label;import fl.controls.TextInput;import flash.display.Sprite;import flash.display.StageAlign;import flash.display.StageScaleMode;import flash.events.Event;import flash.events.MouseEvent;import flash.events.NetStatusEvent;import flash.media.Camera;import flash.media.H264Profile;import flash.media.H264VideoStreamSettings;import flash.media.Microphone;import flash.media.Video;import flash.net.NetConnection;import flash.net.NetStream;public class H264Publisher extends Sprite{public function H264Publisher(){if(this.stage == null){this.addEventListener(Event.ADDED_TO_STAGE, this.onAddedToStage);}else{this.onAddedToStage(null);}}private function onAddedToStage(evt:Event):void{this.stage.align = StageAlign.TOP_LEFT;this.stage.scaleMode = StageScaleMode.NO_SCALE;var urlPanel:Sprite = new Sprite();this.addUrlPanel(urlPanel, onMouseClickStartPublish, onMouseClickStopPublish);var cameraPanel:Sprite = new Sprite();this.addCameraPanel(cameraPanel);var encodingPanel:Sprite = new Sprite();this.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 = new Video();video.x = encodingPanel.x;video.y = encodingPanel.y + 30;this.addChild(urlPanel);this.addChild(cameraPanel);this.addChild(encodingPanel);this.addChild(video);}private var fmsUrl:String;private var fmsStream:String;private function discoveryFmsUrl():void{var url:String = txtUrl.text;if(url.toLowerCase().indexOf("rtmp://") < 0){trace("[error] the url must start with rtmp://", "error");return;}// remove the start rtmp://url = url.substr(url.toLowerCase().indexOf("rtmp://") + "rtmp://".length);var server:String = url.substr(0, url.indexOf("/"));url = url.substr(url.indexOf("/") + 1);var port:String = "1935";if(server.indexOf(":") >= 0){port = server.substr(server.indexOf(":")+1);server = server.substr(0, server.indexOf(":"));}var appIndex:int = -1;for(var i:int = 0; i < this.cbAppLevel.selectedIndex + 1; i++){if(url.indexOf("/", appIndex + 1) < 0){break;}appIndex = url.indexOf("/", appIndex + 1);}var app:String = url.substr(0, appIndex);var stream:String = url.substr(appIndex + 1);// if user input ip address, set the server; otherwise, set the vhost.var serverIsIPAddress:Boolean = true;var serverItems:Array = server.split(".");for(i = 0; i < serverItems.length; i++){if(isNaN(Number(serverItems[i]))){serverIsIPAddress = false;}}fmsUrl = "rtmp://" + server + ":" + port + "/" + app;fmsStream = stream;}private function buildEncodingParameters(publishStream:NetStream, c:Camera, m:Microphone):void{var x264profile:String = (this.cbX264Profile.selectedLabel == "Main") ? H264Profile.MAIN : H264Profile.BASELINE;var x264level:String = this.cbX264Level.selectedLabel;var x264KeyFrameInterval:int = int(this.cbX264KeyFrameInterval.selectedIndex + 1);var cameraWidth:int = int(this.cbCameraSize.selectedLabel.substr(0, this.cbCameraSize.selectedLabel.indexOf("x")));var cameraHeight:int = int(this.cbCameraSize.selectedLabel.substr(this.cbCameraSize.selectedLabel.indexOf("x") + 1));;var cameraFps:Number = Number(this.cbCameraFps.selectedLabel);var cameraBitrate:int = int(this.cbCameraBitrate.selectedLabel);var cameraQuality:int = 85;var microEncodeQuality:int = 8;var microRate:int = 22; // 22 === 22050 Hztrace("[Publish] h.264(x264) encoding parameters: " + "profile=" + x264profile + ", level=" + x264level+ ", keyFrameInterval(gop)=" + x264KeyFrameInterval+ "; video(camera) width=" + cameraWidth+ ", height=" + cameraHeight+ ", fps=" + cameraFps+ ", bitrate=" + cameraBitrate+ ", quality=" + cameraQuality+ "; audio(microphone) encodeQuality=" + microEncodeQuality+ ", rate=" + microRate + "(22050Hz)");var h264Settings:H264VideoStreamSettings = new H264VideoStreamSettings();// we MUST set its values first, then set the NetStream.videoStreamSettings, or it will keep the origin values.h264Settings.setProfileLevel(x264profile, x264level); publishStream.videoStreamSettings = h264Settings;// the setKeyFrameInterval/setMode/setQuality use the camera settings.// http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/media/VideoStreamSettings.html// Note This feature will be supported in future releases of Flash Player and AIR, for now, Camera parameters are used./*h264Settings.setKeyFrameInterval(4);h264Settings.setMode(800, 600, 15);h264Settings.setQuality(500, 0);*/// set the camera and microphone.// setKeyFrameInterval(keyFrameInterval:int):void// keyFrameInterval:int — A value that specifies which video frames are transmitted in full (as keyframes) instead of being //interpolated by the video compression algorithm. A value of 1 means that every frame is a keyframe, a value of 3 means //that every third frame is a keyframe, and so on. Acceptable values are 1 through 48.c.setKeyFrameInterval(x264KeyFrameInterval);// setMode(width:int, height:int, fps:Number, favorArea:Boolean = true):void// width:int — The requested capture width, in pixels. The default value is 160.// height:int — The requested capture height, in pixels. The default value is 120.// fps:Number — The requested rate at which the camera should capture data, in frames per second. The default value is 15.c.setMode(cameraWidth, cameraHeight, cameraFps);// setQuality(bandwidth:int, quality:int):void// bandwidth:int — Specifies the maximum amount of bandwidth that the current outgoing video feed can use, in bytes per second. //To specify that the video can use as much bandwidth as needed to maintain the value of quality, pass 0 for bandwidth. //The default value is 16384.// quality:int — An integer that specifies the required level of picture quality, as determined by the amount of compression // being applied to each video frame. Acceptable values range from 1 (lowest quality, maximum compression) to 100 //(highest quality, no compression). To specify that picture quality can vary as needed to avoid exceeding bandwidth, //pass 0 for quality.// winlin://bandwidth is in bps not kbps. 500*1000 = 500kbps.//quality=1 is lowest quality, 100 is highest quality.c.setQuality(cameraBitrate * 1000, cameraQuality);// if no microphone, donot set the params.if(m == null){return;}// The encoded speech quality when using the Speex codec. Possible values are from 0 to 10. The default value is 6. Higher numbers // represent higher quality but require more bandwidth, as shown in the following table. The bit rate values that are listed represent // net bit rates and do not include packetization overhead.m.encodeQuality = microEncodeQuality;// The rate at which the microphone is capturing sound, in kHz. Acceptable values are 5, 8, 11, 22, and 44. The default value is 8 kHz // if your sound capture device supports this value. Otherwise, the default value is the next available capture level above 8 kHz that // your sound capture device supports, usually 11 kHz.m.rate = microRate;}private var publishStream:NetStream;private var publishConnection:NetConnection;private function onMouseClickStartPublish(evt:MouseEvent):void{// if published, donothingif(publishStream != null){return;}this.btnStartPublish.enabled = false;this.btnStopPublish.enabled = true;this.discoveryFmsUrl();publishConnection = new NetConnection();var conn:NetConnection = publishConnection;conn.client = {};conn.client.onBWDone = function():void{};conn.addEventListener(NetStatusEvent.NET_STATUS, function(evt:NetStatusEvent):void{trace("[Publish][connection] code:" + evt.info.code);switch(evt.info.code){case "NetConnection.Connect.Success":publishStream = new NetStream(conn);// microphone and cameravar m:Microphone = Microphone.getMicrophone(cbMicrophone.selectedIndex);// Remark: the name is the index!var c:Camera = Camera.getCamera(String(cbCamera.selectedIndex));if(c == null){trace("[Publish][error] failed to open camera(name=" + String(cbCamera.selectedIndex) + "): " + cbCamera.selectedLabel, "error");cleanupPublishedStream();break;}else if(c.muted){trace("[Publish][error] open camera(name=" + String(cbCamera.selectedIndex) + ") failed, it's muted: " + cbCamera.selectedLabel, "error");cleanupPublishedStream();break;}buildEncodingParameters(publishStream, c, m);publishStream.addEventListener(NetStatusEvent.NET_STATUS, function(evt:NetStatusEvent):void{trace("[Publish][NetStreamStatus]" + evt.info.code);switch(evt.info.code){case "NetStream.Publish.Start":var h264:H264VideoStreamSettings = publishStream.videoStreamSettings as H264VideoStreamSettings;trace("[Publish] video codec: " + h264.codec + ", profile=" + h264.profile+ ", level=" + h264.level+ ", quality=" + h264.quality+ ", fps=" + h264.fps+ ", gop=" + h264.keyFrameInterval+ ", bandwidth=" + h264.bandwidth+ ", size=" + h264.width + "x" + h264.height);break;case "NetStream.Publish.BadName":cleanupPublishedStream();break;}});publishStream.publish(fmsStream);// attach video and audio.trace("[Publish][debug] start publish, using camera(name=" + String(cbCamera.selectedIndex) + "): " + c.name);publishStream.attachCamera(c);if(m != null && !m.muted){trace("[Publish][debug] start publish, using microphone(name=" + String(cbMicrophone.selectedIndex) + "): " + m.name);publishStream.attachAudio(m);}restartPlayback();break;case "NetConnection.Connect.Rejected":case "NetConnection.Connect.Failed":cleanupPublishedStream();break;}});conn.connect(fmsUrl);}private function cleanupPublishedStream():void{this.btnStartPublish.enabled = true;this.btnStopPublish.enabled = false;if(this.publishStream != null){this.publishStream.close();}if(this.publishConnection != null){this.publishConnection.close();}this.publishStream = null;}public var stream:NetStream;private var conn:NetConnection;private var video:Video;private function restartPlayback():void{// stream is playing, resume it.if(this.stream != null){this.stream.close();}conn = new NetConnection();conn.client = {};conn.client.onBWDone = function():void{};conn.addEventListener(NetStatusEvent.NET_STATUS, function(evt:NetStatusEvent):void{trace("[connection] code:" + evt.info.code + " desc:" + evt.info.description);switch(evt.info.code){case "NetConnection.Connect.Success":stream = new NetStream(conn);video.attachNetStream(stream);//stream.bufferTime = 3;stream.addEventListener(NetStatusEvent.NET_STATUS, function(evt:NetStatusEvent):void{trace("[NetStreamStatus]" + evt.info.code + " desc:" + evt.info.description);});stream.client = {};stream.client.onMetaData = function onMetadata(metadata:Object):void{var o:Object = {};for(var key:String in metadata){o[key] = metadata[key];trace("[metadata] " + "key=" + key + ", value=" + o[key]);}if(metadata.width == undefined){metadata.width = 10;trace("[warning] metadata.width is undefied, set to 10");}if(metadata.height == undefined){metadata.height = 10;trace("[warning] metadata.height is undefied, set to 10");}video.width = metadata.width;video.height = metadata.height;};if(!cbIsLive.selected){stream.play(fmsStream, 0);}else{stream.play(fmsStream);}break;case "NetConnection.Connect.Rejected":case "NetConnection.Connect.Failed":stream.close();stream = null;break;}});conn.connect(fmsUrl);}private function onMouseClickStopPublish(evt:MouseEvent):void{this.cleanupPublishedStream();}private var txtUrl:TextInput;private var btnStartPublish:Button;private var btnStopPublish:Button;private var cbAppLevel:ComboBox;private var cbIsLive:CheckBox;private function addUrlPanel(panel:Sprite, onMouseClickStartPublish:Function, onMouseClickStopPublish:Function):void{var lblUrl:Label = new Label();lblUrl.text = "RTMP Url:";lblUrl.width = 50;panel.addChild(lblUrl);txtUrl = new TextInput();txtUrl.width = 380;txtUrl.x = lblUrl.x + lblUrl.width + 3;panel.addChild(txtUrl);cbIsLive = new CheckBox();cbIsLive.selected = true;cbIsLive.label = "Live";cbIsLive.width = 53;cbIsLive.x = txtUrl.x + txtUrl.width + 0;panel.addChild(cbIsLive);cbAppLevel = new ComboBox();cbAppLevel.addItem({label: "1级App"});cbAppLevel.addItem({label: "2级App"});cbAppLevel.addItem({label: "3级App"});cbAppLevel.addItem({label: "4级App"});cbAppLevel.width = 70;cbAppLevel.x = cbIsLive.x + cbIsLive.width + 0;panel.addChild(cbAppLevel);btnStartPublish = new Button();btnStartPublish.label = "发布流";btnStartPublish.width = 60;btnStartPublish.x = cbAppLevel.x + cbAppLevel.width + 3;btnStartPublish.addEventListener(MouseEvent.CLICK, onMouseClickStartPublish);panel.addChild(btnStartPublish);btnStopPublish = new Button();btnStopPublish.label = "停止发布";btnStopPublish.width = 60;btnStopPublish.enabled = false;btnStopPublish.x = btnStartPublish.x + btnStartPublish.width + 3;btnStopPublish.addEventListener(MouseEvent.CLICK, onMouseClickStopPublish);panel.addChild(btnStopPublish);}private var cbX264Profile:ComboBox;private var cbX264Level:ComboBox;private var cbX264KeyFrameInterval:ComboBox;private var cbCameraSize:ComboBox;private var cbCameraFps:ComboBox;private var cbCameraBitrate:ComboBox;private function addEncodingPanel(panel:Sprite):void{var lblX264Profile:Label = new Label();lblX264Profile.text = "Profile:";lblX264Profile.width = 38;lblX264Profile.y = 2;panel.addChild(lblX264Profile);cbX264Profile = new ComboBox();cbX264Profile.width = 72;cbX264Profile.x = lblX264Profile.x + lblX264Profile.width + 0;panel.addChild(cbX264Profile);cbX264Profile.addItem({label:"Baseline"});cbX264Profile.addItem({label:"Main"});var lblX264Level:Label = new Label();lblX264Level.text = "Level:";lblX264Level.width = 32;lblX264Level.y = 2;lblX264Level.x = cbX264Profile.x + cbX264Profile.width + 1;panel.addChild(lblX264Level);cbX264Level = new ComboBox();cbX264Level.width = 45;cbX264Level.x = lblX264Level.x + lblX264Level.width + 1;panel.addChild(cbX264Level);var x264Levels:Array = ["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"];for(var i:int = 0; i < x264Levels.length; i++){cbX264Level.addItem({label:x264Levels[i]});}cbX264Level.selectedIndex = 8;var lblX264KeyFrameInterval:Label = new Label();lblX264KeyFrameInterval.text = "GOP:";lblX264KeyFrameInterval.width = 29;lblX264KeyFrameInterval.y = 2;lblX264KeyFrameInterval.x = cbX264Level.x + cbX264Level.width + 1;panel.addChild(lblX264KeyFrameInterval);cbX264KeyFrameInterval = new ComboBox();cbX264KeyFrameInterval.width = 87;cbX264KeyFrameInterval.x = lblX264KeyFrameInterval.x + lblX264KeyFrameInterval.width + 1;panel.addChild(cbX264KeyFrameInterval);for(i = 0; i < 48; i++){cbX264KeyFrameInterval.addItem({label:String(i + 1) + " seconds"});}cbX264KeyFrameInterval.selectedIndex = 3;var lblCameraSize:Label = new Label();lblCameraSize.text = "Size:";lblCameraSize.width = 30;lblCameraSize.y = 2;lblCameraSize.x = cbX264KeyFrameInterval.x + cbX264KeyFrameInterval.width + 1;panel.addChild(lblCameraSize);cbCameraSize = new ComboBox();cbCameraSize.width = 82;cbCameraSize.x = lblCameraSize.x + lblCameraSize.width + 1;panel.addChild(cbCameraSize);var sizes:Array = ["176x144", "320x240", "352x240", "352x288", "640x480", "720x480", "720x576", "800x600", "1024x768", "1280x720", "1360x768", "1920x1080"];for(i = 0; i < sizes.length; i++){cbCameraSize.addItem({label:sizes[i]});}cbCameraSize.selectedIndex = 1;var lblCameraFps:Label = new Label();lblCameraFps.text = "FPS:";lblCameraFps.width = 28;lblCameraFps.y = 2;lblCameraFps.x = cbCameraSize.x + cbCameraSize.width + 1;panel.addChild(lblCameraFps);cbCameraFps = new ComboBox();cbCameraFps.width = 58;cbCameraFps.x = lblCameraFps.x + lblCameraFps.width + 1;panel.addChild(cbCameraFps);var fpses:Array = ["1.00", "4.00", "5.00", "6.00", "8.00", "10.00", "12.00", "14.98", "15.00", "20.00", "24.00", "25.00", "29.97", "30.00", "59.94", "60.00"];for(i = 0; i < fpses.length; i++){cbCameraFps.addItem({label:fpses[i]});}cbCameraFps.selectedIndex = 8;var lblCameraBitrate:Label = new Label();lblCameraBitrate.text = "Bitrate:";lblCameraBitrate.width = 40;lblCameraBitrate.y = 2;lblCameraBitrate.x = cbCameraFps.x + cbCameraFps.width + 1;panel.addChild(lblCameraBitrate);cbCameraBitrate = new ComboBox();cbCameraBitrate.width = 58;cbCameraBitrate.x = lblCameraBitrate.x + lblCameraBitrate.width + 1;panel.addChild(cbCameraBitrate);var bitrates:Array = ["10", "50", "100", "200", "350", "500", "650", "800", "950", "1000", "1200", "1500", "1800", "2000", "2500", "20000"];for(i = 0; i < bitrates.length; i++){cbCameraBitrate.addItem({label:bitrates[i]});}cbCameraBitrate.selectedIndex = 3;}private var cbCamera:ComboBox;private var cbMicrophone:ComboBox;private function addCameraPanel(panel:Sprite):void{// cameravar lblCamera:Label = new Label();lblCamera.text = "Available Cameras:";lblCamera.width = 100;panel.addChild(lblCamera);cbCamera = new ComboBox();cbCamera.width = 160;cbCamera.x = lblCamera.x + lblCamera.width + 3;panel.addChild(cbCamera);var cameras:Array = Camera.names;for(var i:int = 0; i < cameras.length; i++){cbCamera.addItem({label:cameras[i]});}// microphonevar lblMicrophone:Label = new Label();lblMicrophone.text = "Available Microphones:";lblMicrophone.width = 120;lblMicrophone.x = cbCamera.x + cbCamera.width + 10;panel.addChild(lblMicrophone);cbMicrophone = new ComboBox();cbMicrophone.width = 180;cbMicrophone.x = lblMicrophone.x + lblMicrophone.width + 3;panel.addChild(cbMicrophone);var microphones:Array = Microphone.names;for(i = 0; i < microphones.length; i++){cbMicrophone.addItem({label:microphones[i]});}}}}
其中用到了FlashCS5的控件,可以将c:\Program Files (x86)\Adobe\Adobe Flash CS5\Common\Configuration\Components\User Interface.fla打开后导出swc,然后在actionscript3项目中引用这个swc就可以了。
- flash actionscript 3.0 publish h264 stream
- flash actionscript 3.0 publish h264 stream
- flash actionscript 3.0 发布H264的视频流
- flash actionscript 3.0 赞
- Flash CS3 ActionScript 3.0入门
- Flash.ActionScript.3.0动画教程_code1
- Flash.ActionScript.3.0动画教程_code2
- Flash.ActionScript.3.0动画教程_code3
- Flash ActionScript 3.0 学习开篇
- Flash ActionScript 3.0 细雨涟漪
- Adobe Flash CS3 ActionScript 3.0 概述
- Flash ActionScript 3.0 面向对象入门教程
- Adobe flash cs3 ActionScript 3.0入门
- Flash MX ActionScript字典
- Flash ActionScript for Designers
- 了解Flash ActionScript
- 积少成多Flash(8) - ActionScript 3.0 网页之获取参数,JavaScript与ActionScript之间的相互调用
- [ActionScript]Flash MX中的ActionScript全集
- Web服务器和servlet容器的区别
- 不再需要数据线:iPhone无线充电底座
- Newton_dynamic物理引擎部分函数说明-未完待续
- mysql 不区别表名的大小写
- 导入CSV包含逗号的内容
- flash actionscript 3.0 publish h264 stream
- Yii中CDbCriteria常用总结
- MySql数据库的安装和使用
- Android学习——TextView 设置中划线 下划线
- 转-ntohl
- Hierarchy Viewer测试工具
- error C2079: CButtonST::m_ToolTip 使用未定义的 class CToolTipCtrl
- VT-X
- 给iOS开发AIR原生扩展的20条建议(转自 james李鹏---译者)