将一系列图像编码成video
如何从Android上的一系列图像/照片创buildvideo文件? 这可以用当前的SDK来完成吗? 还是我需要一个编解码器库?
我同意马克。 在C / C ++库中有ffmpeg ,或者这里是X264。 我不得不说,我没有发现他们或Android NDK易于使用,但这可能是因为我不太了解C / C ++和JNI。 如果您对这条路线感兴趣,那么Android的RockPlayer免费应用程序就有了ffmpeg的预build共享库,可以在Android上使用。 他们声称这些库只使用LGPL组件,但是我想你必须在这方面满足你自己。 关于Java,有一个ffmpeg的端口(不是很奇怪),你可以在这里访问它,但是仍然会调用大部分现有的ffmpeg框架,所以你回到了NDK领域。 使用Java媒体框架(JMF)可以将一系列图像转换为video,但它有以下缺点:
- 数量有限的video格式。
- 不会产生可以在大多数(如果不是全部)Android手机(例如H264或MPEG4)上播放的video。
- JMF代码现在已经很老了,很长一段时间没有进展,臃肿,结构也不好,所以可能会有额外的Java依赖关系,这些依赖关系在Android中没有打包。
我见过的另一个选项是Adobe Air,但它是一个17Mb的有效载荷,一些用户抱怨。
关于ffmpeg和Android NDK,Stack Overflow还有很多其他的问题。
祝你好运。
没有内置的支持。 您需要find一些您需要的Java源代码,或者您可以将一些C / C ++代码转换为库并通过NDK使用。 或者,如果最终目标是将video放在服务器上,请上传图像/照片并让服务器创buildvideo。
ffmpeg
是你的救援队员。 您可以下载Android的FFMPEG端口。 有关更多详细信息,请参阅Android上的FFmpeg问题。
该端口支持几乎所有你需要的东西,包括格式 – input图像格式为GIF,JPG,PNG,BMP等,并输出video格式为AVI,MP4(容器)与大量的编解码器。
您可以使用一个名为JCodec( http://jcodec.org )的免费开源库,其中包含一些stream行的video格式和编解码器的纯Java实现,包括:H.264(AVC),MPEG 1/2,Apple ProRes,JPEG ,MP4(ISO BMF),MPEG PS,MPEG TS,Matroska。
您可以使用下面使用JCodec低级API的CORRECTED类:
public class SequenceEncoder { private SeekableByteChannel ch; private Picture toEncode; private RgbToYuv420 transform; private H264Encoder encoder; private ArrayList<ByteBuffer> spsList; private ArrayList<ByteBuffer> ppsList; private CompressedTrack outTrack; private ByteBuffer _out; private int frameNo; private MP4Muxer muxer; public SequenceEncoder(File out) throws IOException { this.ch = NIOUtils.writableFileChannel(out); // Transform to convert between RGB and YUV transform = new RgbToYuv420(0, 0); // Muxer that will store the encoded frames muxer = new MP4Muxer(ch, Brand.MP4); // Add video track to muxer outTrack = muxer.addTrackForCompressed(TrackType.VIDEO, 25); // Allocate a buffer big enough to hold output frames _out = ByteBuffer.allocate(1920 * 1080 * 6); // Create an instance of encoder encoder = new H264Encoder(); // Encoder extra data ( SPS, PPS ) to be stored in a special place of // MP4 spsList = new ArrayList<ByteBuffer>(); ppsList = new ArrayList<ByteBuffer>(); } public void encodeImage(BufferedImage bi) throws IOException { if (toEncode == null) { toEncode = Picture.create(bi.getWidth(), bi.getHeight(), ColorSpace.YUV420); } // Perform conversion for (int i = 0; i < 3; i++) Arrays.fill(toEncode.getData()[i], 0); transform.transform(AWTUtil.fromBufferedImage(bi), toEncode); // Encode image into H.264 frame, the result is stored in '_out' buffer _out.clear(); ByteBuffer result = encoder.encodeFrame(_out, toEncode); // Based on the frame above form correct MP4 packet spsList.clear(); ppsList.clear(); H264Utils.encodeMOVPacket(result, spsList, ppsList); // Add packet to video track outTrack.addFrame(new MP4Packet(result, frameNo, 25, 1, frameNo, true, null, frameNo, 0)); frameNo++; } public void finish() throws IOException { // Push saved SPS/PPS to a special storage in MP4 outTrack.addSampleEntry(H264Utils.createMOVSampleEntry(spsList, ppsList)); // Write MP4 header and finalize recording muxer.writeHeader(); NIOUtils.closeQuietly(ch); } public static void main(String[] args) throws IOException { SequenceEncoder encoder = new SequenceEncoder(new File("video.mp4")); for (int i = 1; i < 100; i++) { BufferedImage bi = ImageIO.read(new File(String.format("folder/img%08d.png", i))); encoder.encodeImage(bi); } encoder.finish(); } }