Android平台无纸化同屏如何实现实时录像功能

技术背景

我们在做无纸化同屏的时候,好多开发者采集到屏幕、麦克风|扬声器数据,除了需要推RTMP出去,或者启动个轻量级RTSP服务,对外提供个拉流的RTSP URL,别的终端过来拉流(小并发场景),还有个技术需求,就是需要本地实时录像。本文主要介绍屏幕采集的过程中,如何实现推送端录像。

技术实现

实际上,Android同屏,需要录像的话,和采集摄像头数据录像一样,只是数据源不同而已,鉴于不管什么格式的video数据,我们都是投递到模块底层做转换编码,所以本质上没啥差别。

本地录像,我们界面上没有做展示,如果实现,很简单,就是加个开始录像|停止录像按钮即可。

对外提供了二次封装设计如下:

/** NTStreamMediaEngine.java* Author: daniusdk.com* WeChat: xinsheng120** Copyright © 2014~2024 DaniuSDK. All rights reserved.*/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();..../** 启动本地录像*/boolean start_stream_record(String record_directory, int file_max_size);boolean is_stream_recording();void stop_stream_record();boolean is_stream_running();
}

开始录像实现如下:

/** NTStreamMediaProjectionEngineImpl.java* Author: daniusdk.com* WeChat: xinsheng120** Copyright © 2014~2024 DaniuSDK. All rights reserved.*/
@Override
public boolean start_stream_record(String record_directory, int file_max_size) {if (stream_publisher_.is_recording()) {Log.e(TAG, "start_stream_record already recording");return false;}if (!is_video_capture_running()) {Log.e(TAG, "start_stream_record please start_video_capture first");return false;}if (is_null_or_empty(record_directory)) {Log.e(TAG, "start_stream_record record_directory is null");return false;}if (file_max_size < 5) {Log.e(TAG, "start_stream_record file_max_size:" + file_max_size + " error");return false;}Runnable r = new Runnable() {private String record_directory_;private int file_max_size_;@Overridepublic void run() {if (!start_record_internal(this.record_directory_, this.file_max_size_)) {// notify .....}}Runnable set(String record_directory, int file_max_size) {this.record_directory_ = record_directory;this.file_max_size_ = file_max_size;return this;}}.set(record_directory, file_max_size);post_or_execute(r);Log.i(TAG, "start_stream_record record_directory:" + record_directory + ", file_max_size:" + file_max_size);return true;
}@Override
public boolean is_stream_recording() {return stream_publisher_.is_recording();
}

start_record_internal()实现如下:

private boolean start_record_internal(String record_directory, int file_max_size) {if (stream_publisher_.is_recording()) {Log.e(TAG, "start_record_internal already recording");return false;}if (!test_and_create_sdk_instance()) {Log.e(TAG, "start_record_internal create sdk instance failed");return false;}if (!config_record(record_directory, file_max_size)) {Log.e(TAG, "start_record_internal config_record failed");stream_publisher_.try_release();return false;}if (!stream_publisher_.StartRecorder()) {Log.e(TAG, "start_record_internal call sdk start failed");stream_publisher_.try_release();return false;}switch_audio_output_type(audio_output_type_);return true;
}

这里调用的录像设置config_record()实现如下:

private boolean config_record(String record_directory, int file_max_size) {if (is_null_or_empty(record_directory))return false;if (file_max_size < 5)return false;if (null == this.lib_publisher_)return false;String directory = record_directory;int ret = lib_publisher_.SmartPublisherCreateFileDirectory(directory);if (ret != 0) {Log.e(TAG, "try create record directory failed, dir:" + directory);return  false;}if (!stream_publisher_.SetRecorderDirectory(directory)) {Log.e(TAG, "set record directory failed, dir:" + directory);return false;}if (!stream_publisher_.SetRecorderFileMaxSize(file_max_size)) {Log.e(TAG, "set record file max size failed, size:" + file_max_size);return false;}return true;
}

停止录像:

@Override
public void stop_stream_record() {if (!stream_publisher_.is_recording())return;Runnable r = new Runnable() {@Overridepublic void run() {stream_publisher_.StopRecorder();stream_publisher_.try_release();test_and_disable_post_audio();}};post_or_execute(r);
}

总结

Android平台无纸化同屏,如果需要本地录像的话,实现难度不大,只要复用之前开发的录像模块的就可以,对我们来说,同屏采集这块,只是数据源不同而已,如果是自采集的其他数据,我们一样可以编码录像。以上是Android同屏录像设计,感兴趣的开发者,可以跟我单独沟通交流。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/404752.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

vue3基础ref,reactive,toRef ,toRefs 使用和理解

文章目录 一. ref基本用法在模板中使用ref 与 reactive 的区别使用场景 二. reactive基本用法在模板中使用reactive 与 ref 的区别使用场景性能优化 三. toRef基本用法示例在组件中的应用主要用途对比 ref 和 toRef 四. toRefs基本用法示例在组件中的应用主要用途对比 ref 和 t…

基于Arch的轻量级发行版Archcraft结合内网穿透实现远程SSH连接

文章目录 前言1. 本地SSH连接测试2. Archcraft安装Cpolar3. 配置 SSH公网地址4. 公网远程SSH连接5. 固定SSH公网地址6. SSH固定地址连接 前言 本文主要介绍如何在Archcraft系统中安装Cpolar内网穿透工具,并以实现Windows环境ssh远程连接本地局域网Archcraft系统来说明使用内网…

高性能web服务器详解

一、Web服务的基础介绍 正常情况下单次web服务访问的流程简图&#xff1a; 1.1 Web服务介绍 这里介绍的是 Apache 和 NGINX 1.1.1 Apache 经典的Web服务端 Apache 起初由美国的伊利诺伊大学香槟分校的国家超级计算机应用中心开发 目前经历了两大版本分别是 1.X 和 2.X…

笔试练习day5

目录 游游的you题目解析解法方法一贪心方法二 腐烂的苹果题目解析例子1例子2解法多源BFS最短路径代码代码解析 JZ62 孩子们的游戏(圆圈中最后剩下的数)题目解析解法方法一模拟环形链表模拟数组模拟 方法二递推/递归/动态规划状态表示状态转移方程代码 感谢各位大佬对我的支持,如…

Mysql原理与调优-Mysql的内存结构

1.绪论 前面说过InnoDB每次查询数据或者更新数据&#xff0c;都是先以16kb的大小将数据读取到内存中&#xff0c;然后对内存中的数据页进行操作。为了减少磁盘IO&#xff0c;Innodb的会先单独的申请一块连续的空间&#xff0c;将从磁盘中的数据页缓存到这片内存中。这片内存就…

2D Inpainting 与NeRF 3D重建的多视角一致性问题

一 问题&#xff1a; NeRF依赖于输入图像的一致性。NeRF&#xff08;Neural Radiance Fields&#xff09;在生成三维场景时&#xff0c;依赖于从多个视角拍摄的输入图像之间的一致性来准确地推断场景的三维结构和颜色信息。 具体来说&#xff1a; 多视角一致性&#xff1a; Ne…

Hive3:三种常用的复杂数据类型

一、Array类型 1、数据示例 2、实操 元数据 zhangsan beijing,shanghai,tianjin,hangzhou wangwu changchun,chengdu,wuhan,beijin创建表 CREATE TABLE myhive.test_array(name string, work_locations array<string>) ROW FORMAT DELIMITED FIELDS TERMINATED BY \t…

LVM 使用以及配置

逻辑卷管理 (LVM) 是一种用于 Linux 系统的存储管理工具&#xff0c;比传统的磁盘分区方法更灵活。LVM 通过将物理存储设备组合成逻辑卷&#xff0c;使得磁盘空间的管理更加动态和便捷。它提供了物理层的抽象&#xff0c;让用户可以创建跨越多个物理磁盘或分区的逻辑卷。 LVM …

2024年软件测试经典面试题(全三篇)【包含答案】做完面试进入大厂不是梦

前言 迎来的便是金九银十&#xff0c;一直想着说分享一些软件测试的面试题&#xff0c;这段时间做了一些收集和整理&#xff0c;下面共有三篇经典面试题&#xff0c;大家可以试着做一下&#xff0c;答案附在后面&#xff0c;希望能帮助到大家。 软件测试经典面试题&#xff0…

【vue讲解:es6导入导出语法、 vue-router简单使用、登录跳转案例、scoped的使用、elementui使用】

1 es6导入导出语法 # 做项目&#xff1a;肯定要写模块--》导入使用# 默认导出和导入 在某个js中 # 命名导出和导入1.1 默认导出和导入 // #########导出语法########### // export default name // 只导出变量 // export default add // 只导出函数// export default {nam…

android13顶部状态栏里面调节背光 背景闪烁问题

总纲 android13 rom 开发总纲说明 目录 1.前言 2.问题分析 3.代码分析 4.代码修改 5.彩蛋 1.前言 android13顶部状态栏里面调节背光, 背景闪烁问题,会出现画面不全问题,如下图 2.问题分析 这里看起来是由于隐藏的时候,界面显示是一个渐变的隐藏,但是后面的背景又是…

Vue3列表(List)

效果如下图&#xff1a;在线预览 APIs List 参数说明类型默认值bordered是否展示边框booleanfalsevertical是否使用竖直样式booleanfalsesplit是否展示分割线booleantruesize列表尺寸‘small’ | ‘middle’ | ‘large’‘middle’loading是否加载中booleanfalsehoverable是否…

stripe Element 如何使用

这里要准备好几个东西&#xff1a; 一个支付成功过后的回调 还有一个下单的接口 一旦进入这个下单界面&#xff0c;就要去调下单的接口的&#xff0c;用 post, 这个 接口你自己写&#xff0c;可以写在后端中&#xff0c;也可以放到 nextjs 的 api 中。 首先说的是这个下单…

Linux ubuntu 24.04 运行《文明5》游戏,解决游戏中文设置的问题!

Linux ubuntu 24.04 运行《文明5》游戏&#xff0c;解决游戏中文设置的问题&#xff01; 《文明5》是一款回合制经营策略游戏&#xff0c;拼的就是科技发展速度&#xff0c;点的是科技树&#xff0c;抢的就是科技制高点&#xff0c;但是真的是时间漫长&#xff0c;可能需要好几…

会“坐”电梯,能避障碍,AGV无人搬运车进入各行各业

AGV 近年来&#xff0c;自动导引车&#xff08;Automated Guided Vehicle&#xff0c;简称AGV&#xff09;作为一种先进的物流设备&#xff0c;在制造业中广泛应用。AGV是一种能够自主行驶的无人驾驶车辆&#xff0c;通过内置的导航系统和传感器&#xff0c;实现对环境的感知与…

keepalived总结

一、概述 定义&#xff1a;Keepalived是一个用于实现服务器高可用性和负载均衡的软件&#xff0c;通过VRRP&#xff08;Virtual Router Redundancy Protocol&#xff0c;虚拟路由器冗余协议&#xff09;实现故障转移。主要功能&#xff1a; 高可用系统网络服务&#xff1a;能够…

leetcode:1512. 好数对的数目(python3解法)

难度&#xff1a;简单 给你一个整数数组 nums 。 如果一组数字 (i,j) 满足 nums[i] nums[j] 且 i < j &#xff0c;就可以认为这是一组 好数对 。 返回好数对的数目。 示例 1&#xff1a; 输入&#xff1a;nums [1,2,3,1,1,3] 输出&#xff1a;4 解释&#xff1a;有 4 组好…

easyexcel--导入导出实现自定义格式转换

自定义格式 我们在数据库设计的时候经常会有枚举类型&#xff0c;如0表示普通用户&#xff0c;1表示VIP用户等&#xff0c;这在excel导入的时候&#xff0c;我们会填普通用户而不是0&#xff0c;这样就需要用到自定义格式把普通用户转换成0&#xff0c;我写了一个通用的抽象类…

【机器学习】探索机器学习在旅游业的革新之旅

&#x1f4dd;个人主页&#x1f339;&#xff1a;Eternity._ &#x1f339;&#x1f339;期待您的关注 &#x1f339;&#x1f339; ❀目录 &#x1f50d;1. 引言&#x1f4d2;2. 机器学习在旅游需求分析中的应用&#x1f31e;用户行为数据分析&#x1f319;旅客偏好预测模型⭐…

垂直行业数字化表现抢眼 亚信科技全年利润展望乐观

大数据产业创新服务媒体 ——聚焦数据 改变商业 2024年8月14日&#xff0c;亚信科技控股有限公司&#xff08;股票代码&#xff1a;01675.HK&#xff09;公布了公司截至2024年6月30日的中期业绩。 财报数据显示&#xff0c;2024年上半年&#xff0c;亚信科技的营业收入为人民币…