当前位置: 首页 > 知识库问答 >
问题:

Xuggler编码与muxing

滑令
2023-03-14

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

  • 接收原始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格式。在此提前感谢您的帮助。

共有2个答案

昌正奇
2023-03-14

我想你应该看看gstreamer:http://gstreamer.freedesktop.org/你需要寻找一个可以捕捉摄像头输入的插件,然后通过管道将其传输到libx264和aac插件,然后它们通过mpegts muxer传递。

gstream er中的管道如下所示:

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的插件。如果你需要进一步的建议,请告诉我。

洪英豪
2023-03-14

看看Xugler这个示例代码,下面应该可以将视频编码为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);
}

在这种情况下,我相信您的代码负责交错音频和视频:您希望在每次通过循环时调用codeAudio()或codeVideo(),基于可用数据(音频样本块或视频帧)具有较早的时间戳。

您最终可能会使用另一个基于IStreamCoder的低级API,它可以更好地控制各种参数。我认为您不需要使用它。

要回答您提出的具体问题:

(1)“将BufferedImage(M/JPEG)编码为h.264流”-您已经弄清楚了,writer.addVideoStream(..., ICodec. ID.CODEC_ID_H264)确保您获得H.264编解码器。要获取传输流(MPEG2 TS)容器,只需使用扩展名为. ts的文件名调用makeWriter()

(2) “弄清楚原始音频馈送的“BuffereImage等价物”是什么”-即短[]或IAudioSamples对象(两者似乎都能工作,但IAudioSamples必须由一个不那么简单的IBuffer构建)。

(3) “将这个音频类编码成AAC音频流”——调用writer。addAudioStream(…,ICodec.ID.CODEC_ID_AAC,channelCount,sampleRate)

(4) “将两个流多路复用到同一个MPEG-TS容器中”——使用。ts filename,用于设置容器类型。要实现正确的音频/视频同步,可能需要按正确的顺序调用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类图、ToolFactory、IMediaWriter、ICodec。

 类似资料:
  • 问题内容: 我正在尝试使用Xuggler(我 相信 它是在幕后使用的)执行以下操作: 接受原始的MPJPEG视频比特流(来自小型TTL串行相机)并将其编码/转码为h.264;和 接受原始音频bitream(来自麦克风)并将其编码为AAC;然后 将两个(音频和视频)位流一起混合到MPEG-TS容器中 我已经看过/阅读了他们的一些出色的教程,到目前为止,这是我所拥有的: 首先,我想我已经很近了,但是还

  • 问题内容: 是的,我知道FAQ会假装回答此问题,但实际上并非如此。相反,它指示您从源代码构建项目(并且构建说明非常复杂)。那种打败了整个观点:) 让我们省去世界上每个人的麻烦,即不必再构建另一个开源项目,以了解它是否真正解决了他们的问题。Xuggler支持哪些编解码器? 问题答案: FAQ不能回答这个问题的原因是,随着我们发布新版本,它会不断变化,并且要使文档中的列表保持最新状态会花费很长时间。但

  • Xuggler 提供了利用 Java 来解压缩,修改和重新压缩任何媒体或流文件的最简单方式。

  • 我正在编写一个记录屏幕和音频的应用程序。虽然屏幕录制工作完美,但我很难使用JDK库获取原始音频。代码如下: 这个页面有一些伪代码,比如 但是对于,我应该做些什么呢? 此外,还有一个额外的问题——在这种方法中,是否可以从多个麦克风中进行选择? 另请参见:Xuggler编码和muxing

  • 问题内容: 我正在工作的项目是使用Jackson JSON 序列化程序将一堆Java对象转换为String,以便将它们发送到REST服务。 其中一些对象包含敏感数据,因此我编写了自定义序列化程序以将这些对象序列化为JSON字符串,然后对其进行gzip,然后使用; 对其进行加密。 这会将字符串转换为字节数组,因此我在编解码器中使用Base64编码器将字节数组转换为字符串。REST接口背后的自定义反序

  • 源编码与目标编码的不一致. 而中文window系统默认编码GBK,害惨了多少程序员. 要尽量减少出现乱码,我个人认为要做到5码合一, IDE(Eclipse/idea),页面(jsp/其他模板引擎),应用服务器(tomcat等), 源码(Java源码及周边文件),数据库编码. 将Eclipse设置为UTF-8 打开Eclipse安装目录下的eclipse.ini,在最末尾新增一行 -Dfile.