虚拟摄像头/无人直播效果分析,可替抖音/微信

本文介绍了一种利用VCAM、Magisk和LSPosed实现Android虚拟摄像头的方法,通过hook系统Camera API,达到无人直播的效果,适用于抖音和微信。在Magisk的安装过程中,涉及Magisk预装、烧写boot、自动安装模块等问题。同时,文章讨论了解锁设备、防止预装APK被卸载的技巧,并提供了替换视频的路径。在实际应用中,微信使用Camera1,抖音使用Camera2。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、可实现方案

qWhfZ4.png

VCAM + Magisk + Lsposed

android_virtual_cam 基于 Xposed 的虚拟摄像头,采用 hook 方式去勾住系统 Camera 相关 API,然后读取本地指定视频文件进行替换

Magisk 用于 root 系统,刷入系统 boot.img,然后再安装 Riru 和 LSPosed 模块

Riru 模块

LSPosed 模块

qWIEPs.png

二、效果图

qWvSHI.gif

三、实现过程和难点

难点一、Magisk 预装并烧写完成替换 boot

熟悉 Magisk 的伙计都知道,要想成功刷入修补后 boot.img ,需要将设备解锁才行。

以前我的认知都是解锁需要重启进入 BootLoader 模式配合音量键操作才能成功,这样如果

批量生产这种需要默认解锁的特殊设备岂不是要麻烦到家了。后来仔细阅读了 lk 源码,发现

MTK 已经考虑到这种情况了,提供两特殊宏 MTK_BUILD_DEFAULT_UNLOCK 和 MTK_SECURITY_SW_SUPPORT

将其打开后再次编译烧写设备已经是解锁状态,这样就省去了手动解锁麻烦。

配置路径 vendor/mediatek/proprietary/bootable/bootloader/lk/project/xxxx.mk

vendor\mediatek\proprietary\bootable\bootloader\lk\platform\common\boot\avb20\load_vfy_boot.c

int load_vfy_boot(uint32_t bootimg_type, uint32_t addr)
{

#ifdef MTK_SEC_FASTBOOT_UNLOCK_SUPPORT
#if defined(MTK_DM_VERITY_OFF) || defined(MTK_BUILD_DEFAULT_UNLOCK) || !defined(MTK_SECURITY_SW_SUPPORT)
	/* This feature is for test purpose only.
	 * we unlock device without wiping userdata, which should not
	 * happen for MP product. We do this because after userdata
	 * has been wiped, Android will fail to mount userdata and reboot
	 * to recovery to format userdata, and then reboot. If we always
	 * wipe userdata in boot process, Android will never get a properly
	 * formatted userdata.
	 */
#ifdef MTK_SECURITY_SW_SUPPORT
	/* unlock device */
	if (sec_set_device_lock(0) != 0) {
		ret = ERR_AVB_UNLOCK_DEVICE_FAILED;
		goto end;
	}
#endif

解锁后开机时间明显变长了且主屏幕有警告文字提示,这很明显是需要我们避免的。

vendor/mediatek/proprietary/bootable/bootloader/lk/platform/common/boot/vboot_state.c

+       /*video_set_cursor(video_get_rows() / 2, 0);
        video_printf("Orange State\n\n");
        video_printf("Your device has been unlocked and can't be trusted\n");
        video_printf("Your device will boot in 5 seconds\n");
        mtk_wdt_restart();
+       mdelay(5000);*/
        mtk_wdt_restart();

虽然这样处理系统后,烧写开机还是免不了要做一次修补提取 boot.img 操作,然后就可以再次直接刷入提取 boot

重启后 Magsik 可正常工作。对于最终要发放系统版本,发放人员可这样操作,先刷机后开机进行修补提取 boot.img,

将修补后 boot 替换原来编译后 boot, 整个刷机包就是最终烧写固件。

难点二、Magsik 安装依赖模块 Riru 和 LSPosed 需要再次重启

Magisk 成功安装后,底部会多出 4 按钮菜单

qW3eje.png

传统做法手动点击模块按钮,跳转安装页面,从手机 sdcard 下选择预制的 Riruxxx.zip LSPosedxxx.zip

模块的安装顺序必须先 riru 然后再 lsposed,这样操作起来又是更麻烦。好在 Magisk 是开源的,那我们就来自己定制一个

Magisk,实现自动安装模块。源码下载编译可参考之前写的 Magisk 最新版本 V24.1 源码编译踩坑集锦

编译成功后来修改代码吧,虽然是 kotlin 问题不大,盘它。修改思路如下

1、先判断是否成功安装 Magsik,没安装自动跳转然后直接安装

刷机完修补后的boot,开机后需要选推荐安装一次 Magisk 才能正常使用(底部工具栏)

2、安装成功后拷贝 assert 目录下的 riru.zip 和 LSPosed.zip 到 sdcard 根目录

3、跳转安装模块界面先安装 riru 模块,再安装 LSPosed 模块,安装成功重启

这部分的逻辑比较简单就不贴了,直接放个最终的 Magisk.apk

难点三、高版本预装 APK 可卸载

之前也写过参考这篇 android11.0® data分区节点加密控制分析

修改

system/core/init/util.cpp

system/core/rootdir/init.rc

新建 package/app/MagiskAPP 文件夹

Android.mk

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := Magisk
LOCAL_MODULE_TAGS := optional
LOCAL_SRC_FILES := $(LOCAL_MODULE).apk
LOCAL_MODULE_CLASS := APPS
LOCAL_MODULE_SUFFIX := $(COMMON_ANDROID_PACKAGE_SUFFIX)
# LOCAL_PRIVILEGED_MODULE := true
LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
# LOCAL_CERTIFICATE := PRESIGNED
LOCAL_DEX_PREOPT := false
LOCAL_CERTIFICATE := platform
include $(BUILD_PREBUILT)

include $(CLEAR_VARS)
LOCAL_MODULE := VCAM
LOCAL_MODULE_TAGS := optional
LOCAL_SRC_FILES := $(LOCAL_MODULE).apk
LOCAL_MODULE_CLASS := APPS
LOCAL_MODULE_SUFFIX := $(COMMON_ANDROID_PACKAGE_SUFFIX)
# LOCAL_PRIVILEGED_MODULE := true
LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
LOCAL_CERTIFICATE := PRESIGNED
LOCAL_DEX_PREOPT := false
# LOCAL_CERTIFICATE := platform
include $(BUILD_PREBUILT)

经过测试 微信视频通话使用 Camera1

抖音直播使用 Camera2

四、准备替换视频

抖音替换路径 /sdcard/DCIM/Camera1/virtual.mp4

微信替换路径 /sdcard/Android/data/com.tencent.mm/files/Camera1/virtual.mp4

virtual.mp4 用系统相机直接随便录制一个即可,主要是看其具体分辨率。

2022-02-09 14:39:19.398 2179-3231/com.mediatek.ims I/LSPosed-Bridge: 【VCAM】1位参数初始化相机,类:class com.mediatek.ims.internal.VTSource$DeviceHandler$1
2022-02-09 14:39:19.465 2179-3232/com.mediatek.ims I/LSPosed-Bridge: 【VCAM】重建垃圾场
2022-02-09 14:39:19.472 2179-3232/com.mediatek.ims I/LSPosed-Bridge: 【VCAM】打开相机C2
2022-02-09 14:39:19.663 2179-3231/com.mediatek.ims I/LSPosed-Bridge: 【VCAM】surfaceInfo=Surface(name=android.graphics.SurfaceTexture@3131cdf)/@0x6b39b1f
2022-02-09 14:39:19.663 2179-3231/com.mediatek.ims I/LSPosed-Bridge: 【VCAM】获取 c2_preview_Surfcae
2022-02-09 14:39:19.664 2179-3231/com.mediatek.ims I/LSPosed-Bridge: 【VCAM】添加目标:Surface(name=android.graphics.SurfaceTexture@3131cdf)/@0x6b39b1f
2022-02-09 14:39:19.665 2179-3231/com.mediatek.ims I/LSPosed-Bridge: 【VCAM】开始build请求
2022-02-09 14:39:19.672 2179-3231/com.mediatek.ims I/LSPosed-Bridge: 【VCAM】c2_player.setDataSource
2022-02-09 14:39:19.734 2179-3231/com.mediatek.ims I/LSPosed-Bridge: 【VCAM】处理过程完全执行
2022-02-09 14:39:21.105 2179-3231/com.mediatek.ims I/LSPosed-Bridge: 【VCAM】surfaceInfo=Surface(name=android.graphics.SurfaceTexture@3131cdf)/@0xd964558
2022-02-09 14:39:21.106 2179-3231/com.mediatek.ims I/LSPosed-Bridge: 【VCAM】获取 c2_preview_Surfcae_1
2022-02-09 14:39:21.106 2179-3231/com.mediatek.ims I/LSPosed-Bridge: 【VCAM】添加目标:Surface(name=android.graphics.SurfaceTexture@3131cdf)/@0xd964558
2022-02-09 14:39:21.109 2179-3231/com.mediatek.ims I/LSPosed-Bridge: 【VCAM】开始build请求
2022-02-09 14:39:21.191 2179-3231/com.mediatek.ims I/LSPosed-Bridge: 【VCAM】c2_player.setDataSource
2022-02-09 14:39:21.249 2179-3231/com.mediatek.ims I/LSPosed-Bridge: 【VCAM】c2_player_1.setDataSource
2022-02-09 14:39:21.276 2179-3231/com.mediatek.ims I/LSPosed-Bridge: 【VCAM】[c2player1][ Surface(name=android.graphics.SurfaceTexture@3131cdf)/@0xd964558]java.lang.IllegalStateException
2022-02-09 14:39:21.276 2179-3231/com.mediatek.ims I/LSPosed-Bridge: 【VCAM】处理过程完全执行

2022-02-11 13:01:59.107 695-1207/? E/Camera3-OutputStream: configureConsumerQueueLocked: Unable to connect to native window for stream 0
2022-02-11 13:01:59.107 695-1207/? E/Camera3-Stream: finishConfiguration: Unable to configure stream 0 queue: Invalid argument (-22)
2022-02-11 13:01:59.107 695-1207/? E/Camera3-Device: Camera 1: configureStreamsLocked: Can’t finish configuring output stream 0: Invalid argument (-22)
2022-02-11 13:01:59.107 695-1207/? E/CameraDeviceClient: endConfigure: Camera 1: Unsupported set of inputs/outputs provided
2022-02-11 13:01:59.108 769-4340/? I/MtkCam/StreamingPipe/MDPWrapper: [MDPWrapper][p2s] out port count=2, mUseIONFD=0
2022-02-11 13:01:59.108 769-4340/? I/MtkCam/StreamingPipe/MDPWrapper: [MDPWrapper][p2s] out port count=2, mUseIONFD=0
2022-02-11 13:01:59.108 769-4339/? I/MtkCam/fdNodeImp: [config] is FD in secure mode : 0
2022-02-11 13:01:59.108 2200-4306/com.mediatek.ims W/CameraDevice-JV-1: Stream configuration failed due to: endConfigure:505: Camera 1: Unsupported set of inputs/outputs provided
2022-02-11 13:01:59.109 769-4340/? I/MtkCam/StreamingPipe/MDPWrapper: [MDPWrapper][p2s] out port count=2, mUseIONFD=0
2022-02-11 13:01:59.109 2200-4306/com.mediatek.ims E/CameraCaptureSession: Session 0: Failed to create capture session; configuration failed
2022-02-11 13:01:59.109 769-4340/? I/MtkCam/StreamingPipe/MDPWrapper: [MDPWrapper][fpipe.helper] out port count=2, mUseIONFD=0
Dialer: DialerCall.onCameraError - Camera session error: 8003, Call: [DialerCall_1, INCOMING, [Capabilities: rsp_v_txt mut], [Properties: m_volte], children:[], parent:null, conferenceable:[], videoState:Audio Tx Rx, mSessionModificationState:0, CameraDir:-1]

在看雪论坛发现有大佬直接修改 framework 层可实现此功能,后来实操了,发现只能 hook camera1 微信,抖音就不行了,也算是一种思路

在lineageOS16.0 小米6 上 复现无人直播应用

是一款非常受欢迎的视频分享平台,而跳转到微信、QQ或者网页H5的源码程序可以实现在视频中添加跳转链接的功能。下面是一种实现方式的简要说明: 首先,我们需要在的开发者平台上注册账号,并创建一个应用。通过开发者平台,我们可以获取到的SDK和API相关信息。 其次,我们需要了解的视频分享流程。当用户点击视频分享按钮时,我们需要将跳转链接添加到分享链接中。可以通过SDK提供的接口实现这个功能,将跳转链接和视频信息传递给的分享接口即可。 在跳转链接中,我们可以设置对应的微信、QQ或者网页H5的链接地址。当用户点击分享的视频,在打开视频的同时,也会跳转到我们设置的链接地址,实现从到其他平台或者网页的跳转功能。 当然,在实现这个功能时,我们还需要考虑用户的授权问题。例如,跳转到微信或者QQ时,需要用户授权登录。这可以通过SDK提供的接口来实现,将用户的授权信息传递给对应的平台。 总而言之,跳转到微信、QQ或者网页H5的源码程序需要通过的SDK和API来实现。通过将跳转链接添加到分享链接中,并结合用户的授权信息,我们可以在视频中实现跳转到其他平台或者网页的功能。这样就可以让用户在享受视频的同时,进行更多的交互和体验。
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

cczhengv

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值