使用闪存介质服务器录制网络摄像头

时间:2012-07-04 07:30:18

标签: flash video webcam flash-media-server video-recording

我正在尝试创建一个允许用户录制视频消息的网络应用。我正在努力获得最好的质量(即使这意味着上传时间很长)。 我设法使用ns.publish("livestream", "live");进行录制 服务器代码如下所示:

Client.prototype.startRecord = function( source, destination ) {
        trace("recording Stream: " + source + " to: " + destination);
        this.newStream = Stream.get(destination);
        this.fileRecording = destination;
        trace(this.fileRecording);

        if (this.newStream)
        {
            this.newStream.onStatus = function (info) {
                //trace(info.code );
                if (info.code == "NetStream.Play.PublishNotify") {              
                    trace("start recording");
                    this.record();
                }   
            }

            this.newStream.play(source)

        }
    }

    Client.prototype.stopRecord = function() {
        trace("stopping Recording");
        this.newStream.record(false);
        this.newStream.play(false);
    }

    Client.prototype.getFiles = function() {
        var fileRecord = new File("/streams/_definst_/"+this.fileRecording+".flv");

        if (fileRecord.exists)
        {
            return this.fileRecording;
        }

        return "error recording";
    }


    application.onConnect = function(clObj) {
        this.acceptConnection(clObj);
    }

问题是质量不高。我尝试使用ns.publish("livestream", "record");,但它在服务器上制作2个文件并且质量没有提高,有什么建议吗?如果需要,我也可以上传客户端代码。

客户代码:

import flash.media.*;
import flash.events.*;
import flash.net.*;
import flash.utils.getTimer;

var vid:Video;
var mic:Microphone;
var cam:Camera;
var fileListObj:Object = {};
var ns:NetStream;
var nc:NetConnection;
var recordingName:String;

initCamera();

function initCamera ():void
{
    if (Camera.isSupported)
    {
        cam = Camera.getCamera();

        cam.setMode (800, 480, 24);
        //cam.setQuality(0, 90);
        vid = new Video(cam.width,cam.height);

        vid.attachCamera (cam);

        if (Microphone.isSupported)
        {
            mic = Microphone.getEnhancedMicrophone();       
        }

        this.addChildAt (vid, 1);

        vid.x = (800 - vid.width) >> 1;
        vid.y = (480 - vid.height) >> 1;        

        initConnection();
    }
    else
    {
        trace ("no camera");
    }
}


function initConnection ():void
{
    nc = new NetConnection();

    nc.addEventListener (NetStatusEvent.NET_STATUS, netStatusHandler);
    nc.addEventListener (AsyncErrorEvent.ASYNC_ERROR, function (event:AsyncErrorEvent):void {trace("error");});

    nc.connect ("rtmp://adrian7.srfms.com/nabCapture");
}



function recordVideo (event:MouseEvent):void
{
    if (record_mc.label == "Record")
    {
        record_mc.label = "Stop Record";

        var currentTime:Date = new Date();

        recordingName = "myRecording"+getTimer()+""+currentTime.time;

        nc.call ("startRecord", new Responder(startPublish), "livestream", recordingName);


    }
    else
    {
        record_mc.enabled = false;
        record_mc.label = "Record";

        nc.call ("stopRecord", null);
        ns.close();

        nc.call ("getFiles", new Responder(onResultFileListObj, null));     
    }
}

function startPublish (result:Object):void
{
    ns.publish("livestream", "live");
}

function netStatusHandler (event:NetStatusEvent):void
{
    //trace (event.info.code);
    if (event.info.code == "NetConnection.Connect.Success")
    {
        ns = new NetStream(nc);

        ns.attachCamera (cam);
        if (mic)
        {
            ns.attachAudio(mic);
        }

        record_mc.enabled = true;
        record_mc.addEventListener (MouseEvent.CLICK, recordVideo);
    }
}



function onResultFileListObj (resultObj:Object):void 
{
    if (String(resultObj) != "error recording")
    {
        recordingName = String(resultObj);

        see_mc.enabled = true;
        see_mc.addEventListener(MouseEvent.CLICK, function (event:MouseEvent):void {
                        navigateToURL(new URLRequest("http://www.labs.adrian281990.com/fms_demo1/index.php?id=" + recordingName), "_self");
                                });
    }
}

1 个答案:

答案 0 :(得分:0)

使用通用分辨率并避免使用默认的setQuality值

您应该首先进行以​​下更改:

  1. 使用常见的分辨率,如640x480,帧率为30
  2. 避免使用默认cam.setQuality设置并使用cam.setQuality(0,90)
  3. 以上转换为以下客户端AS3代码:

    cam.setMode (640, 480, 24);
    cam.setQuality(0, 90);
    

    <强> cam.setMode(640,480,24);

    当前您正在从网络摄像头请求800x480 @ 24fps。 800x480 @ 24fps并不是一个广泛支持的分辨率,这意味着在大多数网络摄像头上你都会得到网络摄像头响应的任何东西(可能不是最好的质量)。请求常见分辨率(如640 x 480 @ 30fps)将确保您在大多数网络摄像头上获得此功能。

    <强> cam.setQuality(0, 90);

    您的cam.setQuality已被注释,这意味着它将使用默认值转换为:改变图片质量以保持比特率低于130kbits / s(或16384bytes /秒)。

    130kbits / s非常低。使用cam.setQuality(0, 90)告诉Flash使用尽可能多的带宽来保持图片质量为90。

    有关详细信息,请参阅Camera.SetQuality文档。

    Red5版本

    如果您使用的是Red5,则应确保至少使用Red5 1.0.3。这是固定视频录制的第一个版本。所有以前版本的视频录制都已损坏,有关详细信息,请参阅this question

    商业解决方案

    您还应考虑使用HDFVRPipe这样的商业解决方案来处理包括移动设备和转换为.mp4在内的所有内容。

    关于你的“2档案”观察

      

    但它在服务器上制作2个文件并且质量没有提高

    根据您使用的媒体服务器,您可能会获得1,2或更多文件。

    例如,

    Red5将在录制过程中创建2个其他文件(.ser和.info):

    enter image description here

    并且,在第一次播放后,它将创建另一个.meta文件,其中包含关键帧列表,其字节位置和时间戳:

    enter image description here

    以下是这种.meta文件的内容:

    <?xml version="1.0" encoding="UTF-8"?>
    <FrameMetadata audioOnly="false" duration="24074" modified="1446217872000">
        <KeyFrame position="566" timestamp="39"/>
        <KeyFrame position="626" timestamp="40"/>
        <KeyFrame position="14705" timestamp="574"/>
        <KeyFrame position="14765" timestamp="575"/>
        ...
    </FrameMetadata>