我正在尝试使用夏格勒 (我认为它在幕后使用了ffmpeg )来执行以下操作:
我看过/读过他们的一些优秀的教程,到目前为止,我得到的是:
// 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格式。提前感谢您的帮助。
发布于 2012-12-18 14:09:10
查看Xuggler这个示例代码,下面的代码应该可以将视频编码为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);
}容器类型是从文件扩展名猜测的,编解码器是显式指定的。
要对音频和视频进行mux,您可以这样做:
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(),基于这些数据(一段音频样本或一个视频帧)具有较早的时间戳。
在IStreamCoder的基础上,您可能会使用另一个较低级别的API,它可以对各种参数进行更多的控制。我不认为你需要用这个。
要回答你提出的具体问题:
(1)“将BufferedImage (M/JPEG)编码到h.264流中”--您已经知道了,writer.addVideoStream(..., ICodec.ID.CODEC_ID_H264)确保您得到H.264编解码器。要获得传输流(MPEG2 TS)容器,只需调用具有.ts扩展的文件名的makeWriter()。
(2)“找出原始音频输入的”BufferedImage-等效“是什么”--即short[]或IAudioSamples对象(两者似乎都有效,但IAudioSamples必须由IBuffer构造,这要简单得多)。
(3)“将此音频类编码为AAC音频流”--调用writer.addAudioStream(..., ICodec.ID.CODEC_ID_AAC, channelCount, sampleRate)
(4)“将两个流复用到同一个MPEG-TS容器中”--用一个makeWriter()文件名调用.ts,该文件名设置容器类型。要获得正确的音频/视频同步,您可能需要按正确的顺序调用encodeVideo()/encodeAudio()。
始终先传递最早的音频/视频。例如,如果您有长440个样本的音频块(以44000 Hz采样率,440 / 44000 =0.01秒),而视频块仅为25 For (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..。以此类推
只要连续的音频/视频时间戳相对较近,大多数回放设备可能都可以接受这个流,但这就是您为一个完美的mux所做的工作。
有几个文档你可能需要参考:Xuggler类图,ToolFactory,IMediaWriter,ICodec。
发布于 2012-12-15 14:45:26
我认为你应该看看gstreamer:http://gstreamer.freedesktop.org/,你需要寻找能够捕捉相机输入的插件,然后将其输送到libx264和aac插件,然后通过mpegts插件传递给它们。
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的插件。如果你需要更多的指示,请告诉我。
https://stackoverflow.com/questions/13839850
复制相似问题