写点什么

Android 技术分享 | 一行代码实现屏幕、声音采集

作者:anyRTC开发者
  • 2023-04-13
    上海
  • 本文字数:1958 字

    阅读完需:约 6 分钟

Android技术分享 | 一行代码实现屏幕、声音采集

之前发布过一行代码实现安卓屏幕采集编码,并介绍了如何屏幕采集编码并进行了封装,简单的调用即可实现 MediaProjection 权限申请、H264 硬编码、错误处理等功能。本文将介绍新增的功能,还是只需一行代码即可实现屏幕、声音采集。

一行代码实现屏幕采集编码

之前的文章,我们已经介绍过如何一行代码实现安卓屏幕采集编码,这里再次简单介绍一下


ScreenShareKit.init(this).onH264({ buffer, isKeyFrame, w, h, ts ->    //获取编码后的屏幕内容数据}).onStart({    //用户同意采集,开始采集数据}).start()
复制代码


通过这段代码,我们可以实现 MediaProjection 权限申请、H264 硬编码、错误处理等功能。同时,我们也新增了一个 onStart 回调,会在用户同意屏幕采集后回调该方法,更加方便的处理业务。

增加全局屏幕旋转监测

在之前版本中,屏幕旋转,会导致画面变形,宽高错乱。本次更新中,屏幕旋转监测是通过反射监听 IRotationWatcher 来实现的。IRotationWatcher 是一个 AIDL 接口,它定义了一个旋转监测器,用于监测屏幕旋转事件。在 ScreenShare 库中,我们通过反射获取 IRotationWatcher 对象,并注册一个 IRotationWatcher.Stub 实例来监听屏幕旋转事件。当屏幕旋转时,该 Stub 实例会收到回调,并根据旋转角度重置编码器,更改宽高,以保证屏幕方向正确。这里不是简单判断设备是否旋转,而是判断屏幕内容或者其他 app 布局是否旋转。然后重置编码器,更改宽高。始终保持方向正确。


参考:scrcpy

增加 RGBA 数据回调

由于 Android 设备多,各类 CPU 性能不一。很难保证每个设备硬编码后都能够清晰流畅。所以新增一种方式,使用 ImageReader 采集屏幕截图,有很多开源库截图都是利用这个类。ImageReader 是 Android 系统提供的一个用于获取屏幕截图的类,通过 setOnImageAvailableListener 回调,能够不停地获取屏幕变化,并获取 RGBA 数据。在这里我们通过创建一个 ImageReader 对象,并设置其宽高、像素格式等参数来获取屏幕数据。在回调函数中,我们可以获取到每一帧的 RGBA 数据,并进行处理。该实现虽然比硬编码占用的内存高一点,但优势在于非常的均衡,无论性能强悍或是低端的 CPU,都能够得到画质较清晰流畅的数据。


ScreenShareKit.init(this).config(screenDataType = EncodeBuilder.SCREEN_DATA_TYPE.RGBA).onRGBA(object : RGBACallBack {    override fun onRGBA(        rgba: ByteArray,        width: Int,        height: Int,        stride: Int,        rotation: Int,        rotationChanged: Boolean    ) {        //采集的RGBA数据    }}).onStart({    //用户同意采集,开始采集数据}).start()
复制代码

增加屏幕内置声音采集回调

Android 10 已引入 AudioPlaybackCapture API。应用可以借助此 API 复制其他应用正在播放的音频。此功能类似于屏幕采集,但采集对象是音频。主要用例是视频在线播放应用,这些应用希望捕获游戏正在播放的音频。


AudioPlaybackCaptureConfiguration config = (new AudioPlaybackCaptureConfiguration.Builder(mediaProjection)).addMatchingUsage(AudioAttributes.USAGE_MEDIA).build();AudioFormat audioFormat = (new AudioFormat.Builder()).setEncoding(AudioFormat.ENCODING_PCM_16BIT).setSampleRate(sampleRate).setChannelMask(channelConfig).build();audioRecord = new AudioRecord.Builder().setAudioFormat(audioFormat).setBufferSizeInBytes(bufferSizeInBytes).setAudioPlaybackCaptureConfig(config).build();
复制代码


**注意:**应用的音频能否被捕获也取决于应用的 targetSdkVersion


  • 仅支持 Android 10 及以上版本

  • 默认情况下,适配 Android 9.0 及之前版本的应用不允许捕获播放的音频。如要启用该功能,请在应用的 manifest.xml 文件中包含 android:allowAudioPlaybackCapture="true"

  • 默认情况下,适配 Android 10 (API 级别 29)或更高版本的应用允许其他应用捕获其音频。如要停用“捕获播放的音频”功能,请在应用的 manifest.xml 文件中包含 android:allowAudioPlaybackCapture="false"


使用:


ScreenShareKit.init(this).config(audioCapture = true).onAudio(object : AudioCallBack {    override fun onAudio(buffer: ByteArray?, ts: Long) {        //应用的音频数据    }}).onStart({    //用户同意采集,开始采集数据}).start()
复制代码


参考捕获播放的音频:官方文档

增加禁音屏幕内置声音方法

在应用采集过程中,如果不想中断又想禁音,可以调用以下方法。


ScreenShareKit.setMicrophoneMute(true)
复制代码


设置为 true 之后,将会回调空数据,已达到静音效果。反正,恢复正常音频采集。


以上就是本文介绍的一些实用功能。通过这个库,我们可以通过简单的一行代码实现屏幕、声音采集,并且支持全局屏幕旋转监测、RGBA 数据回调、屏幕内置声音采集等功能。这个库使用起来非常方便,项目地址:ScreenShare



发布于: 刚刚阅读数: 3
用户头像

实时交互,万物互联! 2020-08-10 加入

实时交互,万物互联,全球实时互动云服务商领跑者!

评论

发布
暂无评论
Android技术分享 | 一行代码实现屏幕、声音采集_音视频_anyRTC开发者_InfoQ写作社区