Java Xuggler编码与muxing

Java Xuggler编码与muxing,java,ffmpeg,streaming,h.264,xuggler,Java,Ffmpeg,Streaming,H.264,Xuggler,我正在尝试使用(我相信在引擎盖下使用)来执行以下操作: 接受原始MPJPEG视频比特流(来自小型TTL串行摄像机)并将其编码/转码为h.264;及 接收原始音频比特RAM(来自麦克风)并将其编码到AAC;然后 将两个(音频和视频)位记录合并到一个MPEG-TS容器中 我已经观看/阅读了他们的一些优秀教程,到目前为止,我得到的是: // I'll worry about implementing this functionality later, but // involves queryin

我正在尝试使用(我相信在引擎盖下使用)来执行以下操作:

  • 接受原始MPJPEG视频比特流(来自小型TTL串行摄像机)并将其编码/转码为h.264;及
  • 接收原始音频比特RAM(来自麦克风)并将其编码到AAC;然后
  • 将两个(音频和视频)位记录合并到一个MPEG-TS容器中
我已经观看/阅读了他们的一些优秀教程,到目前为止,我得到的是:

// I'll worry about implementing this functionality later, but
// involves querying native device drivers.
byte[] nextMjpeg = getNextMjpegFromSerialPort();

// I'll also worry about implementing this functionality as well;
// I'm simply providing these for thoroughness.
BufferedImage mjpeg = MjpegFactory.newMjpeg(nextMjpeg);

// Specify a h.264 video stream (how?)
String h264Stream = "???";

IMediaWriter writer = ToolFactory.makeWriter(h264Stream);
writer.addVideoStream(0, 0, ICodec.ID.CODEC_ID_H264);
writer.encodeVideo(0, mjpeg);
首先,我认为我离这里很近,但这仍然是不正确的;我只是通过阅读视频代码示例(不是音频-我找不到任何好的音频示例)才做到这一点


从字面上说,我将获得字节级访问原始视频和音频源的权限,这些原始视频和音频源将进入我的Xuggler实现。但就我个人而言,我不知道如何将它们转换成h.264/AAC/MPEG-TS格式。提前感谢您的帮助。

我认为您应该看看gstreamer:您必须寻找能够捕获摄像头输入的插件,然后将其传输到libx264和aac插件,并通过mpegts muxer传递

gstreamer中的管道如下所示:

v4l2src queue-size=15 ! video/x-raw,framerate=25/1,width=384,height=576 ! \
  avenc_mpeg4 name=venc \
alsasrc ! audio/x-raw,rate=48000,channels=1 ! audioconvert ! lamemp3enc name=aenc \
avimux name=mux ! filesink location=rec.avi venc. ! mux. aenc. ! mux.
在这个管道中,mpeg4和mp3编码器被使用,流被多路复用到avi。您应该能够找到libx264和aac的插件。如果您需要更多的指针,请告诉我。

查看,以下内容可以将视频编码为H.264并将其多路复用到MPEG2TS容器中:

IMediaWriter writer = ToolFactory.makeWriter("output.ts");
writer.addVideoStream(0, 0, ICodec.ID.CODEC_ID_H264, width, height);
for (...)
{

   BufferedImage mjpeg = ...;

   writer.encodeVideo(0, mjpeg);
}
根据文件扩展名猜测容器类型,明确指定编解码器

要多路复用音频和视频,请执行以下操作:

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);
}
在本例中,我相信您的代码负责音频和视频的交错:您希望在循环的每次传递中调用encodeAudio()或encodeVideo(),这取决于可用数据(音频样本块或视频帧)具有较早的时间戳

还有另一个较低级别的API,您最终可能会使用它,它提供了对各种参数的更多控制。我想你不需要用这个

要回答您提出的具体问题,请执行以下操作:

(1) “将BuffereImage(M/JPEG)编码为h.264流”-您已经了解了这一点,
writer.addVideoStream(…,ICodec.ID.CODEC\u ID\u H264)
确保获得h.264编解码器。要获取传输流(MPEG2 TS)容器,只需使用扩展名为.TS的文件名调用
makeWriter()

(2) “弄清楚原始音频提要的“BuffereImage等价物”是什么”-即短[]或对象(两者似乎都起作用,但IAudioSamples必须由IBuffer构建,而IBuffer要简单得多)

(3) “将此音频类编码为AAC音频流”-调用
writer.addAudioStream(…,ICodec.ID.CODEC\u ID\u AAC,channelCount,sampleRate)

(4) “将两个流多路传输到同一个MPEG-TS容器中”-使用.TS文件名调用
makeWriter()
,该文件名设置容器类型。要实现正确的音频/视频同步,您可能需要按正确的顺序调用encodeVideo()/encodeAudio()

请务必首先传递最早的音频/视频。例如,如果您有440个采样长的音频块(44000 Hz采样率,440/44000=0.01秒)和25fps(1/25=0.04秒)的视频块,您可以按以下顺序将它们提供给编写器:

video0 @ 0.00 sec
audio0 @ 0.00 sec
audio1 @ 0.01 sec
audio2 @ 0.02 sec
audio3 @ 0.03 sec
video1 @ 0.04 sec
audio4 @ 0.04 sec
audio5 @ 0.05 sec
。。。诸如此类

只要连续的音频/视频时间戳相对较近,大多数播放设备可能都可以播放该流,但这是实现完美多路复用的方法


另外,您可能需要参考一些文档:,,,,

我还应该在赏金文本中提到我没有与Xuggler“结婚”。如果有人能想出如何使用,比如说,
ffmpeg
或其他可以在Linux上运行的工具来完成我需要的一切(在赏金中指定),我也会对这个解决方案感兴趣!你能通过USB连接照相机吗?您知道xuggle是否可以通过USB和SPI上的SPIYes从您的相机读取输入,但我不会使用该选项,原因超出了本问题的范围。唯一真正重要的是,我将以
byte[]
s的形式获取原始音频和视频比特流。如何准确获取
short[]
samples数组?@wrahool:使用TargetDataLine或AudioInputStream,其音频格式为sampleSizeInBits=16,编码=PCM\u签名,bigEndian=false。然后将字节转换为短字符,如下所示:
shortBuf[i]=(byteBuf[2*i+1]我正在从笔记本电脑麦克风获取音频,不过我以后可能还需要从USB麦克风获取音频。@wrahool:如果您愿意,可以将其作为单独的问题发布,听起来有点太复杂,无法在评论中全面探讨。现在已经完成了。