Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/311.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java TargetDataLine和Xuggler通过屏幕视频录制音频_Java_Audio_Video_Sequence_Xuggler - Fatal编程技术网

Java TargetDataLine和Xuggler通过屏幕视频录制音频

Java TargetDataLine和Xuggler通过屏幕视频录制音频,java,audio,video,sequence,xuggler,Java,Audio,Video,Sequence,Xuggler,TargetDataLine是迄今为止,用Java捕获麦克风输入的最简单方法。我想对我用屏幕视频(在屏幕录制软件中)捕获的音频进行编码,以便用户可以创建教程、幻灯片盒等。 我使用Xuggler对视频进行编码。 他们确实有一个关于用视频编码音频的教程,但他们从文件中获取音频。就我而言,音频是实时的。 为了对视频进行编码,我使用了com.xuggle.mediaTool.IMediaWriter。IMediaWriter对象允许我添加视频流,并具有 encodeAudio(int streamIn

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


为了对视频进行编码,我使用了
com.xuggle.mediaTool.IMediaWriter
。IMediaWriter对象允许我添加视频流,并具有
encodeAudio(int streamIndex,short[]示例,long timeStamp,TimeUnit TimeUnit)

如果我可以从目标数据行获取样本,作为
short[]
,我就可以使用它。它返回
字节[]

因此,有两个问题是:

如何用视频对现场音频进行编码? 如何保持音频数据包的正确定时,以便在正确的时间对其进行编码? 参考文献
1.TargetDataLine的DavaDoc:
2.Xuggler文档:


更新 我的视频捕获代码
我最近在这个问题下回答了大部分问题:

代码示例:

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,将告诉您audioSamplesTime所需的时间。这似乎从打开
TargetDataLine
时开始。您需要弄清楚如何获取引用到同一时钟的视频时间戳,这取决于视频设备和/或捕获视频的方式。绝对值并不重要,只要它们都使用相同的时钟。您可以从视频和音频时间中减去初始值(在流开始时),以便时间戳匹配,但这只是一个近似匹配(在实践中可能足够接近)


您需要按严格的时间顺序调用
encodeVideo
encodeAudio
;你可能需要缓冲一些音频和视频,以确保你能做到这一点。更多详细信息。

我已编辑了问题,以便您可以查看代码。在我的例子中,帧速率可以在10到25之间变化,那么如何动态地保持正确的定时呢?PS:我的代码做的东西正确吗?比如以10fps的速度编码等?@LittleChild:你可以将视频时间戳作为从
createscreenscapture
获取帧的时间。“动态保持正确的计时”-只需从音频和视频时间戳中减去第一个值(在流的开始处),然后按时间戳的增加顺序将音频/视频馈送到媒体写入器。@LittleChild:我可以看到一些问题,您确实为可变帧速率流指定了帧速率,但没有指定编解码器。另一种方法更好:)尝试调用
addVideoStream(int-inputIndex,int-streamId,ICodec.ID-codecId,int-width,int-height)取而代之。嘿,我想了想
TargetDataLine
,但这里有一个新问题。请像你写这封信一样写上这封信。这里:附言。你可以使用任何你想要的编解码器,但我建议视频使用
ICodec.ID.CODEC\u ID\u H264
(或测试期间使用
CODEC\u ID\u MPEG2VIDEO
),音频使用
ICodec.ID.CODEC\u ID\u AAC
(或
CODEC\u ID\u MP3
)。确保您的输出容器也可以多路复用以下内容:.mp4或.mkv或.ts应该可以。
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);
}