gpt4 book ai didi

android - 录制视频的问题

转载 作者:太空宇宙 更新时间:2023-11-03 22:54:14 24 4
gpt4 key购买 nike

我正在尝试使用 javacv 以 480*480 分辨率录制视频,就像在 vine 中一样。作为起点,我使用了 https://github.com/bytedeco/javacv/blob/master/samples/RecordActivity.java 中提供的示例正在录制视频(但不是所需的分辨率)并保存。

但问题是android 本身不支持480*480 分辨率。因此,需要进行一些预处理才能获得所需分辨率的视频。

因此,一旦我能够使用 javacv 提供的代码示例录制视频,下一个挑战就是如何预处理视频。研究发现,当所需的最终图像宽度与记录的图像宽度相同时,可以进行有效裁剪。 SO 问题中提供了这样的解决方案,Recording video on Android using JavaCV (Updated 2014 02 17) .我按照该答案中的建议更改了 onPreviewFrame 方法。

    @Override
public void onPreviewFrame(byte[] data, Camera camera) {
if (audioRecord == null || audioRecord.getRecordingState() != AudioRecord.RECORDSTATE_RECORDING) {
startTime = System.currentTimeMillis();
return;
}
if (RECORD_LENGTH > 0) {
int i = imagesIndex++ % images.length;
yuvImage = images[i];
timestamps[i] = 1000 * (System.currentTimeMillis() - startTime);
}
/* get video data */
imageWidth = 640;
imageHeight = 480
int finalImageHeight = 360;
if (yuvImage != null && recording) {
ByteBuffer bb = (ByteBuffer)yuvImage.image[0].position(0); // resets the buffer
final int startY = imageWidth*(imageHeight-finalImageHeight)/2;
final int lenY = imageWidth*finalImageHeight;
bb.put(data, startY, lenY);
final int startVU = imageWidth*imageHeight + imageWidth*(imageHeight-finalImageHeight)/4;
final int lenVU = imageWidth* finalImageHeight/2;
bb.put(data, startVU, lenVU);
try {
long t = 1000 * (System.currentTimeMillis() - startTime);
if (t > recorder.getTimestamp()) {
recorder.setTimestamp(t);
}
recorder.record(yuvImage);
} catch (FFmpegFrameRecorder.Exception e) {
Log.e(LOG_TAG, "problem with recorder():", e);
}
}


}
}

另请注意,此解决方案是为旧版本的 javacv 提供的。生成的视频有一个淡黄色的覆盖层覆盖了 2/3 部分。由于视频未正确裁剪,左侧也有空白部分。

所以我的问题是使用最新版本的 javacv 裁剪视频最合适的解决方案是什么?

按照 Alex Cohn 的建议进行更改后的代码

    @Override
public void onPreviewFrame(byte[] data, Camera camera) {
if (audioRecord == null || audioRecord.getRecordingState() != AudioRecord.RECORDSTATE_RECORDING) {
startTime = System.currentTimeMillis();
return;
}
if (RECORD_LENGTH > 0) {
int i = imagesIndex++ % images.length;
yuvImage = images[i];
timestamps[i] = 1000 * (System.currentTimeMillis() - startTime);
}
/* get video data */
imageWidth = 640;
imageHeight = 480;
destWidth = 480;

if (yuvImage != null && recording) {
ByteBuffer bb = (ByteBuffer)yuvImage.image[0].position(0); // resets the buffer
int start = 2*((imageWidth-destWidth)/4); // this must be even
for (int row=0; row<imageHeight*3/2; row++) {
bb.put(data, start, destWidth);
start += imageWidth;
}
try {
long t = 1000 * (System.currentTimeMillis() - startTime);
if (t > recorder.getTimestamp()) {
recorder.setTimestamp(t);
}
recorder.record(yuvImage);
} catch (FFmpegFrameRecorder.Exception e) {
Log.e(LOG_TAG, "problem with recorder():", e);
}
}


}

使用此代码(destWidth 480)生成的视频的屏幕截图是

video resolution 480*480

接下来我 try catch 一个 destWidth 指定为 639 的视频。结果是

639*480

当 destWidth 为 639 时,视频重复内容两次。 480时,内容重复5次,绿色叠加和失真较多。

此外,当 destWidth = imageWidth 时,可以正确捕获视频。即,对于640*480,没有重复的视频内容,也没有绿色叠加。

将帧转换为 IplImage

当第一次问这个问题时,我没有提到 FFmpegFrameRecorder 中的记录方法现在接受 Frame 类型的对象,而之前它是 IplImage 对象。因此,我尝试通过将 Frame 转换为 IplImage 来应用 Alex Cohn 的解决方案。

//---------------------------------------
// initialize ffmpeg_recorder
//---------------------------------------
private void initRecorder() {

Log.w(LOG_TAG,"init recorder");

imageWidth = 640;
imageHeight = 480;

if (RECORD_LENGTH > 0) {
imagesIndex = 0;
images = new Frame[RECORD_LENGTH * frameRate];
timestamps = new long[images.length];
for (int i = 0; i < images.length; i++) {
images[i] = new Frame(imageWidth, imageHeight, Frame.DEPTH_UBYTE, 2);
timestamps[i] = -1;
}
} else if (yuvImage == null) {
yuvImage = new Frame(imageWidth, imageHeight, Frame.DEPTH_UBYTE, 2);
Log.i(LOG_TAG, "create yuvImage");
OpenCVFrameConverter.ToIplImage converter = new OpenCVFrameConverter.ToIplImage();
yuvIplimage = converter.convert(yuvImage);

}

Log.i(LOG_TAG, "ffmpeg_url: " + ffmpeg_link);
recorder = new FFmpegFrameRecorder(ffmpeg_link, imageWidth, imageHeight, 1);
recorder.setFormat("flv");
recorder.setSampleRate(sampleAudioRateInHz);
// Set in the surface changed method
recorder.setFrameRate(frameRate);

Log.i(LOG_TAG, "recorder initialize success");

audioRecordRunnable = new AudioRecordRunnable();
audioThread = new Thread(audioRecordRunnable);
runAudioThread = true;
}



@Override
public void onPreviewFrame(byte[] data, Camera camera) {
if (audioRecord == null || audioRecord.getRecordingState() != AudioRecord.RECORDSTATE_RECORDING) {
startTime = System.currentTimeMillis();
return;
}
if (RECORD_LENGTH > 0) {
int i = imagesIndex++ % images.length;
yuvImage = images[i];
timestamps[i] = 1000 * (System.currentTimeMillis() - startTime);
}
/* get video data */
int destWidth = 640;

if (yuvIplimage != null && recording) {
ByteBuffer bb = yuvIplimage.getByteBuffer(); // resets the buffer
int start = 2*((imageWidth-destWidth)/4); // this must be even
for (int row=0; row<imageHeight*3/2; row++) {
bb.put(data, start, destWidth);
start += imageWidth;
}
try {
long t = 1000 * (System.currentTimeMillis() - startTime);
if (t > recorder.getTimestamp()) {
recorder.setTimestamp(t);
}
recorder.record(yuvImage);
} catch (FFmpegFrameRecorder.Exception e) {
Log.e(LOG_TAG, "problem with recorder():", e);
}
}


}

但是用这种方法生成的视频只包含绿色帧。

最佳答案

首先,它是预处理,而不是视频后处理。

我不知道你需要对新版本的 javacv 的解决方案进行哪些更改,我希望他们保持库向后兼容。

您的缓冲区宽 640 像素,高 480 像素。您想要裁剪 480x480。

enter image description here

这意味着您需要一个循环将每一行复制到 IplImage,如下所示:

private int imageWidth = 640;
private int imageHeight = 480;
private int destWidth = 480;

@Override
public void onPreviewFrame(byte[] data, Camera camera) {

if (data.length != imageWidth*imageHeight) {
Camera.Size sz = camera.getPreviewSize();
imageWidth = sz.width;
imageHeight = sz.height;
destWidth = imageHeight;
}

ByteBuffer bb = (ByteBuffer)yuvImage.image[0].position(0); // resets the buffer
int start = 2*((imageWidth-destWidth)/4); // this must be even
for (int row=0; row<imageHeight*3/2; row++) {
bb.put(data, start, destWidth);
start += imageWidth;
}
recorder.record(yuvImage);

关于android - 录制视频的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33669457/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com