Android 5开始支持屏幕采集, Android 10支持音频播放采集,不过Android 14用前台服务做屏幕录制时要增加一些处理.
1. app manifest 需要增加:
<manifest>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_MEDIA_PROJECTION" />
<application android:resizeableActivity="true">
<service
android:name="xxx.yyy.MyTestService"
android:foregroundServiceType="mediaProjection"
android:exported="false">
</service>
</application>
</manifest>
2.需要用户先授权投影权限(投影 token), 然后在前台服务中调用:
startForeground(id, notification, ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PROJECTION);
3. 在前台服务中调用MediaProjectionManager.getMediaProjection之前, 需要先调用上面的代码。
4. 用户授权的投影token只能使用一次,就是说只能拿来调用MediaProjectionManager.getMediaProjection一次,也只能调用MediaProjection.createVirtualDisplay一次.
音频播放采集从 Android 10就有了,需要 RECORD_AUDIO 权限和MediaProjection对象. 音频播放采集是依赖屏幕投影的,如果屏幕投影关闭了,音频播放也就采不到了.
具体实现时用到的Android接口不多,不过遇到的各种问题很磨人,为方便项目使用,对实现代码做了封装,支持屏幕采集、音频播放和麦克风采集,同时能输出RTMP流和RTSP流,也支持写录像文件(MP4文件), 接口如下:
/*
* Copyright (C) 1130758427@qq.com. All rights reserved.
* 问题沟通微信: ldxevt
*/
public interface NTStreamMediaEngine {
void register_callback(Callback callback);
void unregister_callback(Callback callback);
void set_resolution_level(int level);
int get_resolution_level();
/*
* 启动媒体投影
*/
boolean start_video_capture(int token_code, android.content.Intent token_data);
boolean is_video_capture_running();
void stop_video_capture();
/*
* 启动麦克风
*/
boolean start_audio_record(int sample_rate, int channels);
boolean is_audio_record_running();
void stop_audio_record();
/*
* Android 10及以上支持, Android10以下设备调用直接返回false
* 需要有RECORD_AUDIO权限
* 要开启媒体投影
*/
boolean start_audio_playback_capture(int sample_rate, int channels);
boolean is_audio_playback_capture_running();
void stop_audio_playback_capture();
/*
* 输出的音频类型
* 0: 不输出音频
* 1: 输出麦克风
* 2: 输出audio playback(Android 10及以上支持)
*/
boolean set_audio_output_type(int type);
int get_audio_output_type();
void set_fps(int fps);
void set_gop(int gop);
boolean set_video_encoder_type(int video_encoder_type);
int get_video_encoder_type();
/*
* 推送RTMP
*/
boolean start_rtmp_stream(String url);
boolean is_rtmp_stream_running();
String get_rtmp_stream_url();
void stop_rtmp_stream();
/*
* 启动RTSP Server, 需要设置端口,用户名和密码可选
*/
boolean start_rtsp_server(int port, String user_name, String password);
boolean is_rtsp_server_running();
void stop_rtsp_server();
/*
* 发布RTSP流
*/
boolean start_rtsp_stream(String stream_name);
boolean is_rtsp_stream_running();
String get_rtsp_stream_url();
void stop_rtsp_stream();
/*
* 启动本地录像
*/
boolean start_stream_record(String record_directory, int file_max_size);
boolean is_stream_recording();
void stop_stream_record();
boolean is_stream_running();
interface Callback {
void on_nt_video_capture_stop();
void on_nt_rtsp_stream_url(String url);
}
}
安卓Demo测试界面:
Windows播放效果截图:
测试时先开启安卓屏幕录制Demo, 在电脑上开个计数器,再打开安卓相机拍摄屏幕上的计数器,录制程序采集安卓相机预览界面,并输出RTMP流和RTSP流, 电脑上播放这两个流并截图, 就可以看延时了,测下来延时很低(安卓后置摄像头拍摄到预览也有延时)。