1

TargetDataLine到目前为止,对我来说,这是在 Java 中捕获麦克风输入的最简单方法。我想用屏幕视频[在屏幕录像机软件中]对我捕获的音频进行编码,以便用户可以创建教程、幻灯片等。
Xuggler用来编码视频。
他们确实有一个关于用视频编码音频的教程,但他们从文件中获取音频。就我而言,音频是实时的。



对我使用的视频进行编码com.xuggle.mediaTool.IMediaWriter。IMediaWriter 对象允许我添加一个视频流,并且
encodeAudio(int streamIndex, short[] samples, long timeStamp, TimeUnit timeUnit)
如果我可以从目标数据行获取样本作为short[]. 它返回byte[]
所以两个问题是:

如何使用视频对实时音频进行编码?

如何保持音频数据包的正确时序,以便在正确的时间对其进行编码?

参考
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打开时开始的。您需要弄清楚如何获取引用同一时钟的视频时间戳,这取决于视频设备和/或捕获视频的方式。只要它们都使用相同的时钟,绝对值就无关紧要。您可以从视频和音频时间中减去初始值(在流开始时),以便时间戳匹配,但这只是一个近似匹配(实际上可能足够接近)。

您需要按照严格递增的时间顺序调用encodeVideoencodeAudio您可能需要缓冲一些音频和一些视频以确保您可以做到这一点。更多细节在这里

于 2012-12-25T15:40:58.860 回答