android视频录制动态添加时间水印
时间: 2023-08-10 16:38:15 浏览: 320
Android视频添加时间水印
如果要在 Android 视频录制过程中动态添加时间水印,可以使用 Camera2 API 实现。Camera2 API 可以获取到每一帧视频的数据,因此可以在每一帧数据上添加时间水印,并将处理后的数据传递给 MediaRecorder 进行录制。
以下是添加动态时间水印的示例代码:
```
private CameraDevice mCameraDevice;
private CaptureRequest.Builder mPreviewBuilder;
private ImageReader mImageReader;
private Surface mRecorderSurface;
private void initCamera() {
CameraManager manager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);
String cameraId = CameraCharacteristics.LENS_FACING_BACK + "";
try {
manager.openCamera(cameraId, new CameraDevice.StateCallback() {
@Override
public void onOpened(@NonNull CameraDevice cameraDevice) {
mCameraDevice = cameraDevice;
startPreview();
}
@Override
public void onDisconnected(@NonNull CameraDevice cameraDevice) {
mCameraDevice.close();
mCameraDevice = null;
}
@Override
public void onError(@NonNull CameraDevice cameraDevice, int i) {
mCameraDevice.close();
mCameraDevice = null;
}
}, null);
} catch (Exception e) {
e.printStackTrace();
}
}
private void startPreview() {
try {
SurfaceTexture surfaceTexture = new SurfaceTexture(0);
surfaceTexture.setDefaultBufferSize(640, 480);
Surface previewSurface = new Surface(surfaceTexture);
mImageReader = ImageReader.newInstance(640, 480, ImageFormat.YUV_420_888, 2);
mImageReader.setOnImageAvailableListener(new ImageReader.OnImageAvailableListener() {
@Override
public void onImageAvailable(ImageReader reader) {
Image image = reader.acquireLatestImage();
ByteBuffer buffer = image.getPlanes()[0].getBuffer();
byte[] data = new byte[buffer.remaining()];
buffer.get(data);
addTimeWatermark(data, image.getWidth(), image.getHeight());
image.close();
}
}, null);
mRecorderSurface = mMediaRecorder.getSurface();
mPreviewBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
mPreviewBuilder.addTarget(previewSurface);
mPreviewBuilder.addTarget(mImageReader.getSurface());
mCameraDevice.createCaptureSession(Arrays.asList(previewSurface, mImageReader.getSurface(), mRecorderSurface), new CameraCaptureSession.StateCallback() {
@Override
public void onConfigured(@NonNull CameraCaptureSession cameraCaptureSession) {
try {
cameraCaptureSession.setRepeatingRequest(mPreviewBuilder.build(), null, null);
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void onConfigureFailed(@NonNull CameraCaptureSession cameraCaptureSession) {
}
}, null);
} catch (Exception e) {
e.printStackTrace();
}
}
private void addTimeWatermark(byte[] data, int width, int height) {
YuvImage yuvImage = new YuvImage(data, ImageFormat.NV21, width, height, null);
ByteArrayOutputStream out = new ByteArrayOutputStream();
yuvImage.compressToJpeg(new Rect(0, 0, width, height), 100, out);
byte[] jpegData = out.toByteArray();
Bitmap bitmap = BitmapFactory.decodeByteArray(jpegData, 0, jpegData.length);
Canvas canvas = new Canvas(bitmap);
canvas.drawText(getCurrentTime(), 10, 10, new Paint());
canvas.save();
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, outputStream);
byte[] outputData = outputStream.toByteArray();
try {
mRecorderSurface.lockCanvas(null).drawBitmap(bitmap, 0, 0, null);
mMediaRecorder.writeSampleData(mRecorderSurface, ByteBuffer.wrap(outputData), new MediaCodec.BufferInfo());
} catch (Exception e) {
e.printStackTrace();
} finally {
mRecorderSurface.unlockCanvasAndPost(canvas);
}
}
```
需要注意的是,在添加时间水印时,要将视频帧转换为 Bitmap 对象,并在 Bitmap 上绘制时间水印。然后,将处理后的数据传递给 MediaRecorder 进行录制。同时,要在 CameraDevice.close() 方法被调用时,释放资源。
阅读全文