有效地将位图数组转换为视频
Efficiently converting an array of bitmaps to video
使用 Jcodec 库,我成功地从位图对象数组生成视频文件并将其存储在 Android 文件系统上。
但是,编码时间太长了。我考虑过缩小每个位图以加快速度,但这似乎不起作用。尽管进行了广泛的研究,我还是很难找到有用的答案。
下面的代码是我当前创建位图的方式,其中 canvasView.getWidth()
和 canvasView.getHeight()
分别对应 1920 x 1280。
public Bitmap loadBitmapFromView(View v) {
Bitmap b = Bitmap.createBitmap(canvasView.getWidth(), canvasView.getHeight(), Bitmap.Config.RGB_565);
Log.i("Downloading", "OWidth: " + b.getWidth() + " --- " + "OHeight: " + b.getHeight());
Canvas c = new Canvas(b);
c.drawColor(Color.WHITE); // Essential
v.draw(c);
v.invalidate();
v.requestLayout();
return b;
}
我注意到当您将这两个参数更改为更小的值时,IE:
Bitmap.createBitmap(256, 256, Bitmap.Config.RGB_565);
编码速度显着加快。
整个视图的大小是1920 x 1280,所以上面显示的createBitmap
方法只会捕获一小部分window( 256 x 256),这不是我所需要的。
我需要帮助找到一种更有效地将位图数组编码为视频的方法,或者使用我正在使用的相同方法,但缩小每个位图,同时保持整个图像的可见性并加快编码过程。
您可以使用 FFmpeg 加快从图像或位图制作视频的过程
ffmpeg 命令:-
File dir = your directory where image stores;
String filePrefix = "picture"; //imagename prefix
String fileExtn = ".jpg";//image extention
filePath = dir.getAbsolutePath();
File src = new File(dir, filePrefix + "%03d" + fileExtn);// image name should ne picture001, picture002,picture003 soon ffmpeg takes as input valid
complexCommand = new String[]{"-i", src + "", "-c:v", "libx264", "-c:a", "aac", "-vf", "setpts=2*PTS", "-pix_fmt", "yuv420p", "-crf", "10", "-r", "15", "-shortest", "-y", "/storage/emulated/0/" + app_name + "/Video/" + app_name + "_Video" + number + ".mp4"};
此处 src = 包含多张图片的目录路径
您可以使用 writingminds 库来轻松地将 ffmpeg 集成到您的项目中
https://github.com/WritingMinds/ffmpeg-android-java
但是 ffmpeg 增加了 apk 大小大约 18-20 mb
我刚刚提出了这个没有外部库的项目。
实施使用这些
implementation 'org.jcodec:jcodec:0.2.5'
implementation 'org.jcodec:jcodec-android:0.2.5'
implementation 'org.jcodec:jcodec-javase:0.2.5'
implementation 'com.writingminds:FFmpegAndroid:0.3.2'
fun creteRootPath(): File? {
var file: File? = null
try {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
file = File(getApplicationContext()
.getExternalFilesDir("")
.toString() + File.separator + "UsamaSd.mp4")
} else {
file = File(Environment
.getExternalStorageDirectory()
.absolutePath.toString()
+ File.separator + "UsamaSd.mp4")
}
if (file?.exists() == true) {
file?.mkdirs()
}
} catch (e: Exception) {
e.printStackTrace()
file // it will return null
}
return file
}
fun convertImagesToVideo() {
try {//Rational(1, 1). SequenceEncoder
val output = creteRootPath()
val enc =
AWTSequenceEncoder.createWithFps(NIOUtils.writableChannel(output),
Rational.R(2, 1))
for (bitmap in arrayOfImagesFinalImages) {
enc.encodeNativeFrame(fromBitmaps(bitmap))
}
enc.finish()
} finally {
NIOUtils.closeQuietly(out);
}
}
fun fromBitmaps(src: Bitmap): Picture {
val dst: Picture = Picture.create(src.width, src.height, RGB)
AndroidUtil.fromBitmap(src, dst)
return dst
}
AndroidUtil class
https://github.com/jcodec/jcodec/blob/master/android/src/main/org/jcodec/common/AndroidUtil.java
使用 Jcodec 库,我成功地从位图对象数组生成视频文件并将其存储在 Android 文件系统上。
但是,编码时间太长了。我考虑过缩小每个位图以加快速度,但这似乎不起作用。尽管进行了广泛的研究,我还是很难找到有用的答案。
下面的代码是我当前创建位图的方式,其中 canvasView.getWidth()
和 canvasView.getHeight()
分别对应 1920 x 1280。
public Bitmap loadBitmapFromView(View v) {
Bitmap b = Bitmap.createBitmap(canvasView.getWidth(), canvasView.getHeight(), Bitmap.Config.RGB_565);
Log.i("Downloading", "OWidth: " + b.getWidth() + " --- " + "OHeight: " + b.getHeight());
Canvas c = new Canvas(b);
c.drawColor(Color.WHITE); // Essential
v.draw(c);
v.invalidate();
v.requestLayout();
return b;
}
我注意到当您将这两个参数更改为更小的值时,IE:
Bitmap.createBitmap(256, 256, Bitmap.Config.RGB_565);
编码速度显着加快。
整个视图的大小是1920 x 1280,所以上面显示的createBitmap
方法只会捕获一小部分window( 256 x 256),这不是我所需要的。
我需要帮助找到一种更有效地将位图数组编码为视频的方法,或者使用我正在使用的相同方法,但缩小每个位图,同时保持整个图像的可见性并加快编码过程。
您可以使用 FFmpeg 加快从图像或位图制作视频的过程
ffmpeg 命令:-
File dir = your directory where image stores;
String filePrefix = "picture"; //imagename prefix
String fileExtn = ".jpg";//image extention
filePath = dir.getAbsolutePath();
File src = new File(dir, filePrefix + "%03d" + fileExtn);// image name should ne picture001, picture002,picture003 soon ffmpeg takes as input valid
complexCommand = new String[]{"-i", src + "", "-c:v", "libx264", "-c:a", "aac", "-vf", "setpts=2*PTS", "-pix_fmt", "yuv420p", "-crf", "10", "-r", "15", "-shortest", "-y", "/storage/emulated/0/" + app_name + "/Video/" + app_name + "_Video" + number + ".mp4"};
此处 src = 包含多张图片的目录路径
您可以使用 writingminds 库来轻松地将 ffmpeg 集成到您的项目中
https://github.com/WritingMinds/ffmpeg-android-java
但是 ffmpeg 增加了 apk 大小大约 18-20 mb
我刚刚提出了这个没有外部库的项目。
实施使用这些
implementation 'org.jcodec:jcodec:0.2.5'
implementation 'org.jcodec:jcodec-android:0.2.5'
implementation 'org.jcodec:jcodec-javase:0.2.5'
implementation 'com.writingminds:FFmpegAndroid:0.3.2'
fun creteRootPath(): File? {
var file: File? = null
try {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
file = File(getApplicationContext()
.getExternalFilesDir("")
.toString() + File.separator + "UsamaSd.mp4")
} else {
file = File(Environment
.getExternalStorageDirectory()
.absolutePath.toString()
+ File.separator + "UsamaSd.mp4")
}
if (file?.exists() == true) {
file?.mkdirs()
}
} catch (e: Exception) {
e.printStackTrace()
file // it will return null
}
return file
}
fun convertImagesToVideo() {
try {//Rational(1, 1). SequenceEncoder
val output = creteRootPath()
val enc =
AWTSequenceEncoder.createWithFps(NIOUtils.writableChannel(output),
Rational.R(2, 1))
for (bitmap in arrayOfImagesFinalImages) {
enc.encodeNativeFrame(fromBitmaps(bitmap))
}
enc.finish()
} finally {
NIOUtils.closeQuietly(out);
}
}
fun fromBitmaps(src: Bitmap): Picture {
val dst: Picture = Picture.create(src.width, src.height, RGB)
AndroidUtil.fromBitmap(src, dst)
return dst
}
AndroidUtil class https://github.com/jcodec/jcodec/blob/master/android/src/main/org/jcodec/common/AndroidUtil.java