1

TargetDataLineこれまでのところ、Java でマイク入力をキャプチャする最も簡単な方法です。ユーザーがチュートリアル、スライドケースなどを作成できるように、[スクリーンレコーダーソフトウェアで]画面のビデオでキャプチャしたオーディオをエンコードしたいです。ビデオのエンコード
に使用Xugglerします。ビデオでオーディオをエンコードするチュートリアルがあり
ますが、ファイルからオーディオを取得します。私の場合、オーディオはライブです。



私が使用するビデオをエンコードするにはcom.xuggle.mediaTool.IMediaWriter. IMediaWriter オブジェクトを使用すると、ビデオ ストリームを追加できます。
encodeAudio(int streamIndex, short[] samples, long timeStamp, TimeUnit timeUnit)
ターゲット データ行からサンプルを として取得できれば、それを使用できますshort[]。戻るbyte[]
したがって、2つの質問は次のとおりです。

ビデオでライブオーディオをエンコードするにはどうすればよいですか?

適切なタイミングでエンコードされるように、オーディオ パケットの適切なタイミングを維持するにはどうすればよいですか?

参照:
1. TargetDataLine の DavaDoc: http://docs.oracle.com/javase/1.4.2/docs/api/javax/sound/sampled/TargetDataLine.html
2. Xuggler ドキュメント: http://build.xuggle。 com/view/Stable/job/xuggler_jdk5_stable/javadoc/java/api/index.html



アップデート

ビデオをキャプチャするための私のコード

public void run(){
        final IRational FRAME_RATE = IRational.make(frameRate, 1);
        final IMediaWriter writer = ToolFactory.makeWriter(completeFileName);
        writer.addVideoStream(0, 0,FRAME_RATE, recordingArea.width, recordingArea.height);
        long startTime = System.nanoTime();

        while(keepCapturing==true){
            image = bot.createScreenCapture(recordingArea);
            PointerInfo pointerInfo = MouseInfo.getPointerInfo();
            Point globalPosition = pointerInfo.getLocation();

            int relativeX = globalPosition.x - recordingArea.x;
            int relativeY = globalPosition.y - recordingArea.y;

            BufferedImage bgr = convertToType(image,BufferedImage.TYPE_3BYTE_BGR);
            if(cursor!=null){
                bgr.getGraphics().drawImage(((ImageIcon)cursor).getImage(), relativeX,relativeY,null);
            }
            try{
                writer.encodeVideo(0,bgr,System.nanoTime()-startTime,TimeUnit.NANOSECONDS);
            }catch(Exception e){
                writer.close();
                JOptionPane.showMessageDialog(null, 
                        "Recording will stop abruptly because" +
                        "an error has occured", "Error",JOptionPane.ERROR_MESSAGE,null); 
            }

            try{
                sleep(sleepTime);
            }catch(InterruptedException e){
                e.printStackTrace();
            }
        }
        writer.close();

    }
4

1 に答える 1

2

私は最近、この質問の下でそのほとんどに答えました:Xuggler encoding and muxing

コードサンプル:

writer.addVideoStream(videoStreamIndex, 0, videoCodec, width, height);
writer.addAudioStream(audioStreamIndex, 0, audioCodec, channelCount, sampleRate);

while (... have more data ...)
{
    BufferedImage videoFrame = ...;
    long videoFrameTime = ...; // this is the time to display this frame
    writer.encodeVideo(videoStreamIndex, videoFrame, videoFrameTime, DEFAULT_TIME_UNIT);

    short[] audioSamples = ...; // the size of this array should be number of samples * channelCount
    long audioSamplesTime = ...; // this is the time to play back this bit of audio
    writer.encodeAudio(audioStreamIndex, audioSamples, audioSamplesTime, DEFAULT_TIME_UNIT);
}

TargetDataLine の場合、getMicrosecondPosition()は、audioSamplesTimeに必要な時間を教えてくれます。TargetDataLineこれは開店時からのようです。同じクロックを参照するビデオ タイムスタンプを取得する方法を理解する必要があります。これは、ビデオ デバイスやビデオのキャプチャ方法によって異なります。両方が同じクロックを使用している限り、絶対値は重要ではありません。タイムスタンプが一致するように、ビデオ時間とオーディオ時間の両方から初期値 (ストリームの開始時) を差し引くことができますが、これは多少おおよその一致にすぎません (実際には十分に近い可能性があります)。

時間の厳密に増加する順序で呼び出す必要がありencodeVideoます。encodeAudioそれができることを確認するために、一部のオーディオと一部のビデオをバッファリングする必要がある場合があります。詳細はこちら

于 2012-12-25T15:40:58.860 に答える