简体   繁体   English

使用Flash Media Server录制网络摄像头

[英]Recording webcam with flash media server

I'm trying to make a web app that lets the user record a video message. 我正在尝试制作一个允许用户录制视频消息的Web应用程序。 I'm trying to get the best quality possible (even if it means long upload times). 我正在尝试获得最好的质量(即使这意味着较长的上传时间)。 I manage to get recording working with ns.publish("livestream", "live"); 我设法通过ns.publish("livestream", "live");进行录音ns.publish("livestream", "live"); The server code looks like this: 服务器代码如下所示:

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);
    }

The problem is that the quality is not great. 问题是质量不是很好。 I tried using ns.publish("livestream", "record"); 我尝试使用ns.publish("livestream", "record"); , but its making 2 files on the server and quality doesn't improve, any suggestion? ,但是在服务器上制作2个文件并且质量没有提高,有什么建议吗? I can also upload the client code if you need it. 如果您需要,我也可以上传客户端代码。

Client code: 客户代码:

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");
                                });
    }
}

Use a common resolution and avoid the default setQuality values 使用通用分辨率,避免使用默认setQuality值

You should start by making the following to changes: 您应该首先进行以​​下更改:

  1. Use a common resolution like 640x480 and a frame rate of 30 使用普通分辨率,例如640x480,帧频为30
  2. Avoid the default cam.setQuality settings and use cam.setQuality(0,90) 避免使用默认的cam.setQuality设置,并使用cam.setQuality(0,90)

the above translates in the following client AS3 code: 以上翻译为以下客户端AS3代码:

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

cam.setMode(640,480,24);

What happens is that you're currently requesting 800x480@24fps from the webcam. 发生的情况是您当前正在从网络摄像头请求800x480 @ 24fps。 800x480@24fps is not a widely supported resolution which means on most webcams you'll get whatever the webcam responds with (which might not be the best quality). 800x480 @ 24fps并非广泛支持的分辨率,这意味着在大多数网络摄像头中,您将获得网络摄像头响应的所有内容(这可能不是最佳质量)。 Requesting a common resolution like 640 x 480 @ 30fps will ensure you're getting just that on most webcams. 要求使用640 x 480 @ 30fps之类的通用分辨率,可以确保您在大多数网络摄像头上都能得到满意的分辨率。

cam.setQuality(0, 90);

Your cam.setQuality is commented which means it will use the default values which translates into: vary the picture quality to keep the bitrate under 130kbits/s ( or 16384bytes/second). cam.setQuality进行了注释,这意味着它将使用默认值转换为:更改图片质量,以将比特率保持在130kbits / s(或16384bytes / second)以下。

130kbits/s is VERY LOW. 130kbits / s非常低。 Use cam.setQuality(0, 90) to tell Flash to use as much bandwidth as needed to keep the picture quality at 90. 使用cam.setQuality(0, 90)告诉Flash使用所需的带宽以将图片质量保持在90。

See Camera.SetQuality documentation for more info. 有关更多信息,请参见Camera.SetQuality文档。

Red5 version Red5版本

If you're using Red5, you should make sure you're using at least Red5 1.0.3 . 如果使用Red5,则应确保至少使用Red5 1.0.3 It's the 1st version with video recording fixed. 这是固定视频录制的第一个版本。 All previous versions had video recording broken, see this question for details. 所有以前的版本都中断了视频录制,有关详细信息,请参阅此问题

Commercial solutions 商业解决方案

You should also consider using a commercial solution like HDFVR or Pipe which handle everything including mobile and the conversion to .mp4 . 您还应该考虑使用诸如HDFVRPipe之类的商业解决方案,该解决方案可以处理包括移动设备和转换为.mp4在内的所有内容。

Regarding your "2 files" observation 关于“ 2个文件”的观察

but its making 2 files on the server and quality doesn't improve 但是它在服务器上制作了2个文件并且质量没有提高

Depending on the media server you're using you might get 1, 2 or more files. 根据您使用的媒体服务器,您可能会获得1个,2个或更多文件。

Red5 for example will create 2 other files during the recording process (.ser and .info): 例如, Red5将在录制过程中创建另外两个文件(.ser和.info):

在此处输入图片说明

and, after the 1st playback, it will create another .meta file which holds the list of keyframe, their byte position and timestamp: 在第一次播放之后,它将创建另一个.meta文件,其中包含关键帧列表,其字节位置和时间戳:

在此处输入图片说明

Here's the contents of such a .meta file: 这是.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>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM