4

Windows8システムでRED51.0Finalをセットアップしましたが、記録を正しく機能させようとしています。私が読んだチュートリアルでは、クライアント側(Flash内)でデータをバッファリングし、バッファが空になったら接続を閉じます。

私が抱えている問題は、バッファの記録を開始すると、バッファが空であるとすぐに報告することです(NetStream.Buffer.Empty)。バッファが実際にいっぱいになる場所で1〜2回動作させましたが、何らかの理由でそのように動作しなくなりました。

サーバー側のファイルが増え続けているため、カメラをネットストリームから切り離した後でも、クライアントがサーバーにデータを送信していることがわかります。現時点での私の解決策は、録音が停止してから60秒待ってから、接続を閉じることです。

興味深いのは、送信するパケットがなくなると、サーバー側でファイルがmystream.serからmystream.flvに切り替わり、サイズが大きくならないことです。このイベントが発生するのを待ってから、ストリームを閉じることができることをクライアントに通知するために、サーバー側でコードを作成することを考えていました。

これはアクションスクリプトへの私の最初の進出なので、ここで完全に間違ったことをしている可能性があります。私にお知らせください。

編集これがクライアントコードです

<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
               xmlns:s="library://ns.adobe.com/flex/spark"
               xmlns:mx="library://ns.adobe.com/flex/mx"
               xmlns:ns1="*"
               minWidth="955" minHeight="600" applicationComplete="init()" >

    <fx:Script>
        <![CDATA[

            import flash.display.DisplayObject;
            import flash.display.Sprite;
            import flash.events.NetStatusEvent;
            import flash.media.Camera;
            import flash.media.H264Level;
            import flash.media.H264Profile;
            import flash.media.H264VideoStreamSettings;
            import flash.media.Video;
            import flash.net.NetConnection;
            import flash.net.NetStream;


            var cam:Camera = Camera.getCamera();
            var mic:Microphone = Microphone.getMicrophone();
            var nc:NetConnection = new NetConnection();
            var activeStream:NetStream;
            private var bufferCheckTimer:Timer;
            var recordHalted:Boolean = false;


            protected function init(): void{
                recordButton.enabled = false;
                stopButton.enabled = false;
                nc.addEventListener(NetStatusEvent.NET_STATUS, onNetStatus);            
                nc.connect("rtmp://localhost/oflaDemo");
                nc.client = this;
            }

            public function onMetaData(info:Object):void {

                trace("playback called onMetaData");        
            }

            public function onBWDone(... rest) : void {
                // have to have this for an RTMP connection
                trace('onBWDone');
            }

            public function onBWCheck(... rest) : uint {
                trace('onBWCheck');
                //have to return something, so returning anything :)
                return 0;
            }


            protected function onNetStatus(event:NetStatusEvent):void{
                trace(event.info.code);
                if(nc.connected)
                {
                    SetupCameraAndMic();
                    recordButton.enabled = true;
                    stopButton.enabled = true;
                }           
            }

            protected function SetupCameraAndMic(): void{
                activeStream = new NetStream(nc);
                activeStream.bufferTime = 60;   
                activeStream.client = this;
                activeStream.addEventListener(NetStatusEvent.NET_STATUS, handleStreamStatus,false,0,true);


                var h264Settings:H264VideoStreamSettings = new H264VideoStreamSettings();
                h264Settings.setProfileLevel(H264Profile.BASELINE, H264Level.LEVEL_2);
                activeStream.videoStreamSettings = h264Settings;

                cam.addEventListener(StatusEvent.STATUS, handleCameraStatus, false, 0, true);
                mic.addEventListener(StatusEvent.STATUS, handleMicrophoneStatus, false, 0, true);

                cam.setMode(320,240, 15);
                cam.setQuality(0, 80);
                cam.setKeyFrameInterval(7);

                mic.rate = 44;
                mic.gain = 75;
                mic.setSilenceLevel(0);
                mic.setUseEchoSuppression(true);



                activeStream.attachCamera(cam);
                activeStream.attachAudio(mic);  
                videoContainer.attachCamera(cam);






            }

            private function handleCameraStatus(e:StatusEvent):void {
                trace("handleCameraStatus - " + e.code);
                switch(e.code) {
                    case 'Camera.muted':
                        // Show a message
                        break;
                    case 'Camera.Unmuted':              
                        //finishCamAndMicSetup();
                        break;
                }
            }


            private function handleMicrophoneStatus(e:StatusEvent):void {
                trace("handleMicrophoneStatus - " + e.code);
                switch(e.code) {
                    case 'Microphone.Muted':
                        // Show a message
                        break;
                    case 'Microphone.Unmuted':              
                        //finishCamAndMicSetup();
                        break;
                }
            }


            private function handleStreamStatus(e:NetStatusEvent):void {
                switch(e.info.code) {
                    case 'NetStream.Buffer.Empty':
                        trace("NetStream.Buffer.Empty");
                        break;
                    case 'NetStream.Buffer.Full':
                        trace("NetStream.Buffer.Full");
                        break;
                    case 'NetStream.Buffer.Flush':
                        trace("NetStream.Buffer.Flush");
                        break;
                }
            }

            protected function recordButton_clickHandler(event:MouseEvent):void
            {
                if(activeStream == null)
                {
                    SetupCameraAndMic();
                }
                if(activeStream != null){
                    var tempDate:Date = new Date();
                    var uniqueFileName:String = "RecordME_" + String(tempDate.getMinutes()) + String(tempDate.getMilliseconds());

                    bufferLabel.text = ""+ activeStream.bufferTime;
                    activeStream.publish(uniqueFileName, "record");
                    bufferCheckTimer = new Timer(100);
                    bufferCheckTimer.addEventListener(TimerEvent.TIMER, handleBufferCheck, false, 0, true);
                    bufferCheckTimer.start();

                }

            }

            private function handleBufferCheck(e:TimerEvent):void {
                if(activeStream != null) {
                    trace("Buffer: " + activeStream.bufferLength);
                    statusLabel.text = "Buffer: " + activeStream.bufferLength;
                    if (recordHalted == true) {
                        if ( activeStream.bufferLength == 0 ) {
                            activeStream.close();
                            activeStream = null;



                            bufferCheckTimer.stop();
                            bufferCheckTimer.removeEventListener(TimerEvent.TIMER, handleBufferCheck);
                            bufferCheckTimer = null;

                            // OK - playback time
                            //doRecordingPlayback();
                        }
                    }


                if (bufferCheckTimer != null) {
                    bufferCheckTimer.reset();
                    bufferCheckTimer.start();
                }
            }
            }

            protected function stopButton_clickHandler(event:MouseEvent):void
            {

                activeStream.attachCamera(null);
                activeStream.attachAudio(null); 
                videoContainer.attachCamera(null);                      
                recordHalted = true;

            }

        ]]>
    </fx:Script>

    <fx:Declarations>
        <!-- Place non-visual elements (e.g., services, value objects) here -->
    </fx:Declarations>
    <mx:VideoDisplay id="videoContainer" x="158" y="53" width="640" height="480"
                    chromeColor="#3C2020" />
    <s:Button id="recordButton" x="396" y="546" label="Record"
              click="recordButton_clickHandler(event)"/>
    <s:Button id="stopButton" x="491" y="546" label="Stop Recording"
              click="stopButton_clickHandler(event)"/>
    <s:Label id="statusLabel" x="158" y="555" width="207"/>
    <s:Label x="14" y="408" text="Buffer Set to:"/>
    <s:Label id="bufferLabel" x="91" y="408" text="0"/>
</s:Application>

ありがとう

4

3 に答える 3

1

現在、実行中のRTMPサーバーがないため、コードに表示されている内容についてコメントしています。

ストリームを公開(記録)するときに、最初にバッファリングについて得たアドバイスはあまり良い考えではないかもしれません。おそらく、チュートリアルは公開ではなく、既存のストリームをサブスクライブすることでした。その場合、バッファリングは素晴らしいアイデアです。

bufferTimeを60秒に設定しています。ドキュメントbufferTimeには、ライブレコーディングの場合は0に設定する必要があると書かれています。つまり、カメラ/マイクによって生成されたらすぐにデータを送信する必要があります。

次はTimerあなたが使っていることです。これは、記録が停止したことを検出するために、バッファー長をチェックしているようです。録音が停止するのは、実際には2つの場合だけです。

  • ユーザーが「停止」ボタンをクリックし、コードがそれを停止したとき
  • サーバーまたは他の何かがサーバーを停止させるシナリオ(ネットワークの問題など)

NetStatusEventタイマーを使用してをチェックする代わりに、ハンドラーメソッド(handleStreamStatus())を使用してメッセージ「NetStream.Record.Stop」をチェックすることをお勧めしますbufferLength。これにより、ユーザーが「停止」をクリックする以外の理由で記録が停止したことをコードが検出できます。

タイマーが問題の原因である可能性があります。大きなbufferTime値を設定した場合でも、Red 5サーバーでは機能しないか、動作が異なる場合があります。または、サーバー側の設定によって上書きされる場合があります。とにかく、ポイントはbufferLength録音が停止したかどうかを検出するために使用されません。

でディスパッチされる有用なメッセージがたくさんありNetStatusEventます。それらを読んで、シナリオで役立つメッセージがあるかどうかを確認することをお勧めします。それらはかなり信頼性が高く、発生する可能性のあるほとんどすべての状況を処理するようです。

最後に気付いたのは(問題ではありませんが、修正する価値があります)、マイクでエコー抑制を有効にしますが、拡張マイクを入手しない限り、それは機能しません。

var mic:Microphone = Microphone.getEnhancedMicrophone();
于 2012-12-19T20:34:58.400 に答える
1

これは、RED5の最終V1.0リリースのバグの結果だと思います。0.80バージョンに戻しましたが、正常に録音できます。

于 2012-12-25T04:06:27.950 に答える
0

録音は、キューのしきい値を変更することにより、Red5V1.0.2でうまく機能します。私はjobmaと呼ばれるビデオ履歴書のウェブサイトがビデオを非常にうまく記録しているのを見ました。彼らはred5を使用しているようです

于 2014-01-15T14:08:08.857 に答える