视频转图片
简而言之就是把视频的每一帧保存为图片,使用MediaMetadataRetriever
String dir = Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + "输出图片" + File.separator;
new Thread(new Runnable() {
@Override
public void run() {
// 创建文件夹
File folder = new File(dir);
if (!folder.exists()) {
folder.mkdir();
}
int fps = 15;
// 这里以raw下的视频为例
Uri videoUrI = Uri.parse("android.resource://" + getPackageName() + "/" + R.raw.test_5s);
MediaMetadataRetriever retriever = new MediaMetadataRetriever();
retriever.setDataSource(MainActivity.this, videoUrI);
// 视频总长度(ms)
String duration = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION);
// 以每秒15帧所需要的时间
int seconds = Integer.parseInt(duration) / 1000 * fps;
Log.d("MainActivity", "seconds:" + seconds);
for (int i = 0; i < seconds; i++) {
// 注意此处的getFrameAtTime传入的单位是微秒
Bitmap bitmap = retriever.getFrameAtTime(i * 1000 * 1000 / fps, MediaMetadataRetriever.OPTION_CLOSEST);
if (bitmap == null) continue;
}
}
}).start();
这样就能获取到相应的图片了,我们也可以保存到本地
public void saveBitmap(Bitmap bitmap) {
FileOutputStream fos;
try {
String name = "";
fos = new FileOutputStream(name, false);
bitmap.compress(Bitmap.CompressFormat.PNG, 100, fos);
fos.flush();
fos.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
图片转视频
有时候需要处理视频里的图像,就需要把视频分解处理完再进行合成,需要用到AndroidSequenceEncoder
new Thread(new Runnable() {
@Override
public void run() {
File folder = new File(dir);
if (!folder.exists()) {
folder.mkdir();
}
AndroidSequenceEncoder encoder = null;
File videoFile = new File(dir + "out.mp4");
try {
int fps = 15;
encoder = AndroidSequenceEncoder.createSequenceEncoder(videoFile, fps);
// 此处就是对本地获取的bitmap进行合并
Bitmap tempBitmap = null;
encoder.encodeImage(tempBitmap);
} catch (IOException e) {
e.printStackTrace();
}
try {
encoder.finish();
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
整合
如果先分解,再保存本地,最后读取进行合成比较繁琐,所以一般在分解时直接进行图像处理操作,最后进行合成
完整代码
new Thread(new Runnable() {
@Override
public void run() {
File folder = new File(dir);
if (!folder.exists()) {
folder.mkdir();
}
AndroidSequenceEncoder encoder = null;
// 设置输出路径
File videoFile = new File(dir + "out.mp4");
try {
int fps = 15;
encoder = AndroidSequenceEncoder.createSequenceEncoder(videoFile, fps);
Uri videoUrI = Uri.parse("android.resource://" + getPackageName() + "/" + R.raw.test_5s);
System.out.println(videoUrI);
MediaMetadataRetriever retriever = new MediaMetadataRetriever();
retriever.setDataSource(MainActivity.this, videoUrI);
String duration = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION);
int seconds = Integer.parseInt(duration) / 1000 * fps;
Log.d("MainActivity", "seconds:" + seconds);
for (int i = 0; i < seconds; i++) {
Bitmap bitmap = retriever.getFrameAtTime(i * 1000 * 1000 / fps, MediaMetadataRetriever.OPTION_CLOSEST);
if (bitmap == null) continue;
// 这里就可以对图像进行相关操作
// 处理完后加到encoder中
Bitmap tempBitmap = null;
encoder.encodeImage(tempBitmap);
}
} catch (IOException e) {
e.printStackTrace();
}
Log.d("MainActivity", "处理结束");
try {
encoder.finish();
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
当然这个有一个很大的缺点,就是非常耗时,实测10s的视频从分解到合并大约需要3分钟,听说使用ffmpeg
效率能有成倍提升,等后续使用上了再发一篇。
参考文章
Android平台下的图片/视频转Ascii码图片/视频 (一) (github持续更新)
android_图片转视频_image2video