技术背景
我们在做Android平台RTSP|RTMP播放器的时候,有这样的技术诉求,播放端需要支持随时实时截图快照功能。实际上,这块,我们前些年就实现了,本blog,介绍下如何实现播放端的实时截图快照。
Android平台RTSP|RTMP播放端实时截图快照功能实现,可以用很多方式,常见的方式比如:
- 使用 TextureView:TextureView 是一个用于显示视频内容的视图,可以通过设置 SurfaceTextureListener 来监听视频帧的更新。在 onSurfaceTextureUpdated 方法中,可以获取当前的视频帧并进行截图。
- 利用 FFmpeg 库:FFmpeg 是一个强大的开源多媒体框架,可以在 Android 上进行编译和使用。通过调用 FFmpeg 的 API,可以对 RTSP 流进行解码,并获取视频帧的数据。然后,可以将视频帧数据保存为图片文件。
- 借助第三方播放模块:SmartPlayer可以实现 RTSP|RTMP播放器的视频截图功能,通常提供了相应的 API 和方法,可以方便地进行截图操作。
技术实现
在探讨Android平台播放器截图快照之前,我们先看保存jpeg还是png,二者区别在哪里?
图像质量差别
PNG:
- 支持无损压缩,能够保留图像的细节和质量,尤其对于具有复杂颜色变化或渐变的图像效果更好。
- 适合保存需要高质量图像的场景,例如截图中包含精细的图形、文本或需要进行后续的编辑处理。
- 但是,由于无损压缩,文件大小通常比 JPEG 大。
JPEG:
- 采用有损压缩算法,可以在一定程度上控制图像质量和文件大小的平衡。
- 对于一般的视频截图,JPEG 的图像质量通常已经足够,特别是在颜色变化相对简单、没有过多细节的情况下。
- 可以通过调整压缩质量参数来控制文件大小和图像质量之间的权衡。
适用场景
如果截图主要用于以下场景,可以考虑使用 PNG:
- 需要高质量的图像,用于打印、专业设计或对图像质量要求较高的场合。
- 截图中包含复杂的图形、文本或需要进行精确的编辑处理。
- 需要保留透明背景或与其他具有透明元素的图像进行合成。
如果截图主要用于以下场景,可以考虑使用 JPEG:
- 对文件大小有限制,例如在移动设备上存储大量截图或进行网络传输。
- 图像质量要求不是特别高,主要用于一般的查看和分享。
- 不需要透明背景或复杂的编辑处理。
接口设计
本文以大牛直播SDK的SmartPlayer播放器为例,介绍下,如何设计实时截图快照的接口。考虑到实际使用场景,我们jpeg和png两种格式,都做了支持。可以参考“拉流端快照”调用实时截图快照功能。
/*
* SmartPlayerJniV2.java
* Copyright © 2014~2024 daniusdk.com All rights reserved.
*/
/**
* 新的截图接口, 支持JPEG和PNG两种格式
* @param compress_format: 压缩格式, 0:JPEG格式, 1:PNG格式, 其他返回错误
* @param quality: 取值范围:[0, 100], 值越大图像质量越好, 仅对JPEG格式有效, 若是PNG格式,请填100
* @param file_name: 图像文件名, 例如:/dirxxx/test20231113100739.jpeg, /dirxxx/test20231113100739.png
* @param user_data_string: 用户自定义字符串
* @return {0} if successful
*/
public native int CaptureImage(long handle, int compress_format, int quality, String file_name, String user_data_string);
针对播放端的封装设计如下:
public boolean CaptureImage(int compress_format, int quality, String file_name, String user_data_string) {
if (!check_native_handle())
return false;
return OK == lib_player_.CaptureImage(get(), compress_format, quality, file_name, user_data_string);
}
外部调用:
/*
* SmartPlayer.java
* Copyright © 2014~2024 daniusdk.com All rights reserved.
*/
class ButtonPullCaptureImageListener implements View.OnClickListener {
public void onClick(View v) {
if (!stream_player_.is_player_running())
return;
if (null == capture_image_date_format_)
capture_image_date_format_ = new SimpleDateFormat("yyyyMMdd_HHmmss_SSS");
String timestamp = capture_image_date_format_.format(new Date());
String imageFileName = timestamp;
String image_path = imageSavePath + "/" + imageFileName;
int quality;
boolean is_jpeg = true;
if (is_jpeg) {
image_path += ".jpeg";
quality = 100;
}
else {
image_path += ".png";
quality = 100;
}
boolean capture_ret = stream_player_.CaptureImage(is_jpeg?0:1, quality, image_path, "test cix");
Log.i(TAG, "capture image ret:" + capture_ret + ", file:" + image_path);
}
}
总结
Android平台RTSP|RTMP播放器实现实时截图快照,选择JPEG还是 PNG 格式取决于具体的需求和应用场景。如果对图像质量要求较高且不关心文件大小,可以选择 PNG;如果需要控制文件大小且对图像质量要求不是特别苛刻,可以选择 JPEG。以上抛砖引玉,对RTSP|RTMP播放模块设计和使用感兴趣的开发者,可以单独跟我沟通探讨。