无人直播硬改系统-技术分析

前段时间接触到了部分手机的无人直播系统。

说是无人直播,实际上应该算是视频转录播放功能。并不是完全的无人操作,还是需要有人录制视频,然后操作手机播放

从想法上,大概也能猜到是使用了 mp4 的帧,去替换摄像头的帧,从而实现视频流的替换,做到无人直播

无人直播系统实现原理

实际上就是用 mp4 的帧替换掉 Camera 的视频帧

Camera 视频流分析

做 Android 开发的都知道,要想实现视频直播,需要调用 Camera 预览,才能获取到视频流数据

如果使用旧的 Camera Api,那么调用的是 Camera.open() 方法,获取到Camera 对象,设置回调,视频流数据会通过回调返回,是 byte[] 数组

如果使用新的 Camera2 APi,那么需要构造 CaptureRequest ,经过许多操作,从而获取到每一帧的 Image 对象,视频流就在每一个 Image 对象中,用户自行编写代码可以获取到 byte[] 数组

如何实现视频流替换?

经过上面分析,可以知道,每一帧视频流都是使用回调,从而提供给 APP 的,那么能否修改这个回调,在提供给 APP 前,将里面的 byte[] 替换掉呢?

其实是可以的,实现方式主要有两种,一种是使用 Xposed 框架 Hook 系统,在回调执行时替换

xposed 框架实现方式有可能会被检测到,从 app 角度出发,可以检测手机上是否安装 Xposed 框架、检测当前堆栈是否有 Xposed 的栈信息等等。

另一种是修改系统 framework ,在系统层面实现视频流的替换,这里简单介绍第二种

定制系统实现视频流替换

如果要自行定制系统,那么选择一款开源的系统必不可少。
目前开源使用比较广泛的是 Lineage OS 。魔趣系统也有

但时至今日(2021),还在频繁更新的是 Lineage OS

既然第一步思路已经明确,在 Framework 的 Camera 中替换 byte[] 数组。那么如何获取 mp4 的 byte[] 数组?

如果使用系统原生提供的 Api,那么可以使用 MediaCodec

MediaCodec 解码视频时,一般要求传入 SurfaceView ,实现视频画面展示

实际上 MediaCodec 可以获取 Image 对象,自行从 Image 对象中取出 byte[] 数组即可。然后在合适的地方替换掉视频流

需要考虑的兼容问题

当然,大致思路如此。但实际上视频流有多种格式:NV21 YUV420 等等。对于这些不同的视频流格式,需要自行转换。

实际上实现定制系统替换视频流的步骤对于个人开发者而言,还是比较麻烦的

首先需要使用 Ubuntu 编译开源系统,然后修改 Framework,解码 mp4 ,替换视频流。

简单的替换当然可以实现。但如果使用系统层面替换视频流,那么需要处理的问题就比较多了,例如视频帧率、视频分辨率、视频流的格式、Mp4 解码格式、App 兼容性,错误处理等等

结尾

目前手上有多款无人直播系统:

小米6

红米6 pro

红米 note8

有具体需求可以直接联系:wx_zhibo8888

不仅提供授权,如果有需要购买整套后台系统的。也可以联系

2021/09/14 更新:加量不加价,现无人直播搭配一对一聊天互动。免费有年卡

微信图片_20210427135515.jpg
https://pan.netsite.cc/chfs/shared/6773D7A1-62A2-494A-BB52-78053E5AA578.jpeg

很抱歉,我不是一个可以运行代码的程序,无法为您提供完整的源代码和报告。但我可以简要介绍如何在NS3中编写纺锤型网络,并使用不同的拥塞控制算法进行性能测试。 1. 编写纺锤型网络 在NS3中,我们可以使用TopologyHelper类来构建网络拓扑。对于八个节点的纺锤型网络,可以按照以下方式实现: ``` Ptr<Node> n0 = CreateObject<Node>(); Ptr<Node> n1 = CreateObject<Node>(); Ptr<Node> n2 = CreateObject<Node>(); Ptr<Node> n3 = CreateObject<Node>(); Ptr<Node> n4 = CreateObject<Node>(); Ptr<Node> n5 = CreateObject<Node>(); Ptr<Node> n6 = CreateObject<Node>(); Ptr<Node> n7 = CreateObject<Node>(); // 创建点对节点 PointToPointHelper pointToPoint; pointToPoint.SetDeviceAttribute("DataRate", StringValue("5Mbps")); pointToPoint.SetChannelAttribute("Delay", StringValue("2ms")); // 设置节点之间的连接 NetDeviceContainer devices; devices.Add(pointToPoint.Install(n0, n1)); devices.Add(pointToPoint.Install(n1, n2)); devices.Add(pointToPoint.Install(n2, n3)); devices.Add(pointToPoint.Install(n3, n4)); devices.Add(pointToPoint.Install(n4, n5)); devices.Add(pointToPoint.Install(n5, n6)); devices.Add(pointToPoint.Install(n6, n7)); devices.Add(pointToPoint.Install(n7, n0)); // 安装网络协议栈 InternetStackHelper stack; stack.InstallAll(); ``` 上述代码中,我们创建了八个节点,并使用PointToPointHelper类创建点对点的连接。接下来,我们将八个节点两两相连,构成一个纺锤型网络。最后,我们使用InternetStackHelper类安装网络协议栈。 2. 使用不同的拥塞控制算法 NS3提供了多种拥塞控制算法,例如TCP NewReno、TCP Vegas、TCP Cubic等。我们可以在仿真程序中选择不同的算法来测试其性能。 ``` // 创建Socket和Application uint16_t port = 50000; Address sinkAddress(InetSocketAddress(Ipv4Address::GetAny(), port)); PacketSinkHelper packetSinkHelper("ns3::TcpSocketFactory", sinkAddress); ApplicationContainer sinkApps = packetSinkHelper.Install(nodes.Get(0)); sinkApps.Start(Seconds(0.0)); sinkApps.Stop(Seconds(simulationTime + 0.1)); OnOffHelper onoff("ns3::TcpSocketFactory", sinkAddress); onoff.SetAttribute("OnTime", StringValue("ns3::ConstantRandomVariable[Constant=1]")); onoff.SetAttribute("OffTime", StringValue("ns3::ConstantRandomVariable[Constant=0]")); onoff.SetAttribute("DataRate", DataRateValue(DataRate("5Mbps"))); onoff.SetAttribute("PacketSize", UintegerValue(1000)); // 安装TCP协议 Config::SetDefault("ns3::TcpSocket::SegmentSize", UintegerValue(1000)); Config::SetDefault("ns3::TcpSocketBase::MaxWindowSize", UintegerValue(50000)); Config::SetDefault("ns3::TcpL4Protocol::SocketType", StringValue("ns3::TcpNewReno")); ApplicationContainer clientApps = onoff.Install(nodes.Get(1)); clientApps.Start(Seconds(0.0)); clientApps.Stop(Seconds(simulationTime + 0.1)); ``` 上述代码中,我们创建了一个TCP Socket和一个TCP Application,并使用不同的拥塞控制算法来测试网络性能。在这里,我们选择了TCP NewReno算法。使用Config::SetDefault()函数可以设置TCP Socket的一些参数,例如最大窗口大小等。 3. 性能测试和报告 在仿真程序中,我们可以使用Simulator::Run()函数来运行仿真。在仿真结束后,我们可以获取一些性能指标,例如吞吐量、延迟、丢包率等,并根据这些指标来评估不同的拥塞控制算法。 ``` Simulator::Stop(Seconds(simulationTime + 0.1)); Simulator::Run(); // 获取性能指标 uint64_t totalPacketsThrough = DynamicCast<PacketSink>(sinkApps.Get(0))->GetTotalRx(); double throughput = totalPacketsThrough * 8 / (simulationTime * 1000000.0); // Mbps double avgDelay = 0; for (uint32_t i = 0; i < clientApps.GetN(); ++i) { Ptr<OnOffApplication> onoffApp = DynamicCast<OnOffApplication>(clientApps.Get(i)); Time startTime = onoffApp->GetStartTime(); Time stopTime = onoffApp->GetStopTime(); double thisDelay = (stopTime.GetSeconds() - startTime.GetSeconds()) * 1000.0; avgDelay += thisDelay; } avgDelay /= clientApps.GetN(); // ms uint64_t totalPacketsDropped = DynamicCast<PacketSink>(sinkApps.Get(0))->GetLost(); double packetLossRate = totalPacketsDropped * 1.0 / totalPacketsThrough; // 输出性能指标 std::cout << "Throughput: " << throughput << " Mbps" << std::endl; std::cout << "Average Delay: " << avgDelay << " ms" << std::endl; std::cout << "Packet Loss Rate: " << packetLossRate * 100 << "%" << std::endl; ``` 上述代码中,我们获取了网络的吞吐量、平均延迟和丢包率等性能指标,并输出到控制台。 根据上述代码,我们可以编写出完整的仿真程序,并根据不同的拥塞控制算法进行测试。在测试中,我们可以使用如下代码切换不同的拥塞控制算法: ``` Config::SetDefault("ns3::TcpL4Protocol::SocketType", StringValue("ns3::TcpNewReno")); // 使用TCP NewReno算法 Config::SetDefault("ns3::TcpL4Protocol::SocketType", StringValue("ns3::TcpVegas")); // 使用TCP Vegas算法 Config::SetDefault("ns3::TcpL4Protocol::SocketType", StringValue("ns3::TcpCubic")); // 使用TCP Cubic算法 ``` 最终,我们可以根据实验结果,撰写不同拥塞控制算法对网络性能的影响的详细报告。
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值