【Flutter】双路视频播放方案

最近在做双路视频播放,就是在一个页面播放两个视频。我遇到的问题就是音频焦点冲突问题,在下面说明。

什么是双路视频播放(来自AI)

双路视频播放(Dual-Video Playback),从字面上理解,就是指在一个屏幕或应用界面上,同时解码和渲染两个独立的视频流

可以把它想象成有两列火车在两条并行的轨道上同时行驶,你可以同时看到两列火车的状态。这两个视频流可以有多种关系和布局方式。

核心特征

  1. 两个独立的视频源: 这不是将一个视频画面分割成两半,而是实实在在地处理两个不同的视频文件或网络流。例如,一个是 video_A.mp4,另一个是 video_B.mp4

  2. 同时播放: 两个视频在时间上是同步或并行播放的。播放/暂停/快进等操作可能联动控制两个视频,也可能允许独立控制。

  3. 精确同步(关键特性): 在很多场景下,双路视频播放的难点和核心在于保持两个视频画面的精确时间同步。例如,如果视频A的第5秒100毫秒对应的是视频B的第5秒100毫秒,那么在播放时必须保证它们始终对齐,不能出现一个快一个慢的情况。

  4. 灵活的布局: 两个视频的画面可以有多种呈现方式:

    • 画中画 (Picture-in-Picture, PiP):一个小视频窗口悬浮在一个大视频窗口之上。
    • 左右分屏 (Side-by-Side):屏幕一分为二,左边播放一个视频,右边播放另一个。
    • 上下分屏 (Top-and-Bottom):屏幕一分为二,上边播放一个视频,下边播放另一个。
    • 叠加融合 (Overlay/Blending):一个视频作为背景,另一个半透明地叠加在上面。

常见的应用场景

双路视频播放技术非常有价值,因为它能提供单一视频无法实现的信息维度和交互体验。

应用领域具体场景描述示例
在线教育/网络课程一路视频播放老师的讲课画面,另一路同步播放课件PPT或屏幕操作的录像。网易云课堂、Coursera等平台,老师头像在角落,主屏幕是课件。
视频剪辑/后期制作在调色或添加特效时,一路播放原始素材,另一路实时播放处理后的效果,方便进行对比。Adobe Premiere Pro, Final Cut Pro 中的对比视图功能。
体育赛事直播/分析一路播放赛场的全景视角,另一路播放某个运动员的特写视角或精彩回放。足球比赛中,同时展示球场全景和某个球星的个人镜头。
安防监控在一个屏幕上同时显示来自不同摄像头的实时监控画面。大楼的安保中心,监控墙上显示着多个区域的实时视频。
无障碍功能 (Accessibility)一路播放主视频内容,另一路在角落同步播放手语翻译的视频。很多新闻发布会或官方视频会提供手语翻译版本。
3D/VR/360°视频这是一种特殊形式的双路视频,系统为左眼和右眼分别渲染一个视频流,从而创造出立体感和沉浸感。YouTube VR, Oculus TV 等 VR 应用。
互动视频/游戏允许用户在不同视角或故事线之间切换,系统在后台可能需要同时准备好多个视频流以实现无缝切换。一些互动电影或真人游戏。

技术挑战

实现稳定流畅的双路视频播放并非易事,尤其是在移动端。

  1. 性能消耗巨大: 解码两个视频流(尤其是高清视频)需要双倍的CPU/GPU计算资源。这会显著增加设备的功耗、发热量,并可能导致卡顿或掉帧。这也是为什么你之前会遇到内存溢出等问题的原因之一,处理双路视频对内存管理的要求更高。

  2. 同步难题: 保持两个视频流的精确同步是一个巨大的挑战。网络延迟的抖动(Jitter)、解码速度的差异都可能导致音画或两个画面之间出现偏移。需要复杂的时钟同步机制来校准。

  3. 音轨处理: 两个视频通常都有自己的音轨。如何处理音频?

    • 只播放其中一个视频的音频?
    • 将两个音轨混合(Mix)在一起?
    • 让用户自己选择听哪一个?
      这都需要在产品设计和技术实现上仔细考虑。
  4. 复杂的播放器控制逻辑: 一个播放器现在需要管理两个视频源的状态,播放/暂停、快进/快退、缓冲状态、错误处理等逻辑都变得复杂了一倍。

总而言之,双路视频播放是一项强大的功能,它通过在同一时间呈现更多维度的视觉信息,极大地丰富了应用的功能和用户体验,但同时也对应用的性能优化和技术实现提出了更高的要求。

 

初方案

`video_player` 插件

创建两个独立的 `VideoPlayerController` 实例,分别控制两个视频的播放。

代码

写在开头,重点就是被注释掉的那句,其实没必要往下看。

    VideoPlayerController controller1 = VideoPlayerController.networkUrl(Uri.parse(videoUrl),//videoPlayerOptions: VideoPlayerOptions(mixWithOthers: true), //是的,一开始没加这句!!!这就是问题所在);VideoPlayerController controller2 = VideoPlayerController.networkUrl(Uri.parse(videoUrl),//videoPlayerOptions: VideoPlayerOptions(mixWithOthers: true),);

 组件代码,只是简单的模拟

@override
Widget build(BuildContext context) {return Scaffold(body: Center(child: Row(children: <Widget>[Expanded(child: _controller1.value.isInitialized? AspectRatio(aspectRatio: _controller1.value.aspectRatio,child: VideoPlayer(_controller1), //这里): Container(),),Expanded(child: _controller2.value.isInitialized? AspectRatio(aspectRatio: _controller2.value.aspectRatio,child: VideoPlayer(_controller2),//这里): Container(),),],),),floatingActionButton: FloatingActionButton(onPressed: () {togglePlayPauseBoth();},child: Icon(_controller1.value.isPlaying ? Icons.pause : Icons.play_arrow,),),);
}void setVolumeBoth(double volume) {controller1?.setVolume(volume);  //注意这里少了一个}void togglePlayPauseBoth() {final bool isPlaying = controller1?.value.isPlaying ?? false;if (isPlaying) {pauseBoth();} else {playBoth();}}void playBoth() {controller1?.play();controller2?.play();}void pauseBoth() {controller1?.pause();controller2?.pause();}void seekBoth(Duration position) {controller1?.seekTo(position);controller2?.seekTo(position);}

问题描述

点击播放只有第一个视频播放,而且播放按钮play_arrow -> pause -> play_arrow。

原因分析

经过了一些不必要的弯路,我终于看到了日志

D/AudioManager(31189): dispatching onAudioFocusChange(-1) ...

 这一行日志就是问题的“确凿证据”。它告诉我们,系统正在向您的应用发送一个“音频焦点丢失” (AUDIOFOCUS_LOSS) 的通知。

问题根源:音频焦点冲突

  1. 什么是音频焦点? 在Android系统中,为了避免多个应用同时播放声音造成混乱,只有一个应用可以在同一时间“持有”音频焦点。
  2. 发生了什么? 当您调用 playBoth() 时,视频播放器1(controller1)和视频播放器2(controller2同时向系统请求音频焦点。
  3. 系统如何反应? Android系统看到来自同一个应用的第二个音频请求,会认为第一个请求应该被放弃。因此,它会立即给第一个请求者发送一个AUDIOFOCUS_LOSS通知。
  4. video_player插件的默认行为video_player插件在收到“音频焦点丢失”的通知后,会非常“懂事”地自动暂停播放。

其他方案

1、使用 `multi_video_player` 插件
2、使用 `video_player_mux` 插件

 怎么使用我也只看了官网例子,没有实践,有空补上。

一些废话,记录bug解决过程

没有发日志之前AI越走越弯 

问题1:

 一开始这里出现的问题是点击播放只有第一个视频播放,而且播放按钮play_arrow -> pause -> play_arrow。

一开始没给AI日志信息,所以分析是两个控制器状态不统一,给出了解决方案1。

解决方案1:

核心是将播放/暂停的命令统一处理,并建立一个单向的同步机制:始终以后置视频的状态为准,强制前置视频跟随。

问题2:

由于上诉修改产生了问题2。因为强制两个视频状态同步,主打同生共死,所以两个视频他们一起停了,按钮play_arrow -> pause -> play_arrow。

解决方案2:

撤回解决方法1。

后面还在ai的指导下尝试了

1、将一个视频静音---->没用。

2、只播放一个视频永远只让一个播放器(主播放器)真正执行play()pause()操作,另一个播放器(从播放器)只通过seekTo()来被动地同步画面,从而绝不请求音频焦点。---->卡顿非常明显,pass。

 

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

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

相关文章

笔试——Day25

文章目录第一题题目思路代码第二题题目&#xff1a;思路代码第三题题目&#xff1a;思路代码第一题 题目 笨小猴 思路 模拟 统计每个字符出现的次数&#xff0c;用最大减最小&#xff0c;判断是不是质数&#xff1b; 质数的判断使用试除法&#xff1b; 代码 第二题 题目&…

【C#学习Day15笔记】拆箱装箱、 Equals与== 、文件读取IO

前言在C#第15天的学习中&#xff0c;我深入探索了类型转换机制、对象比较原理和文件操作技术三大核心主题。这些知识是构建高效、健壮程序的关键基础。本文完整保留我的课堂实践代码和命名体系&#xff0c;通过结构化梳理帮助大家掌握这些核心概念。所有代码示例均来自我的实际…

发电类电力业务许可证申请条件

基本条件&#xff1a;法人资格&#xff1a;申请人必须是依法注册的企业法人。 财务能力&#xff1a;应具有与所申请从事的电力业务相适应的财务能力。 专业人员要求&#xff1a;生产运行负责人、技术负责人、安全负责人和财务负责人需具备至少3年以上与申请从事的电力业务相关的…

JavaScript 高效入门指南:从基础到实战(VSCode 版)

废话不多说&#xff0c;直接上干货&#x1f600; 一、先搞定工具&#xff1a;VSCode 配置成「JS 开发神器」 工欲善其事&#xff0c;必先利其器。用 VSCode 写 JavaScript&#xff0c;这几个配置能让你效率翻倍&#xff1a; 1. 必装插件&#xff08;直接在 VSCode 插件商店搜…

《人形机器人的觉醒:技术革命与碳基未来》——类人关节设计:柔性驱动革命之液压人工肌肉

目录&#xff1a;一、人工肌肉的种类及人形机器人适用情况二、人形机器人用人工肌肉科研机构及其最新成果进展三、液压人工肌肉种类及工作机制四、液压人工肌肉适用人形机器人的性能要求和局限性五、液压人工肌肉材料技术进展及其限制与突破六、波士顿动力Spot的液压静液传动系…

26数据结构-顺序表

&#x1f4cc;有序顺序表的合并 #define MAX_SIZE 20 struct SeqList {int data[MAX_SIZE];int length; }; void mergeArray(SeqList &L1,SeqList &L2,SeqList &L) {int i0,j 0;while(i<L1.length && j<L2.length){if(L1.data[i]<L2.data[j])L.da…

25电赛e题 控制激光开关电路

e题明确说了禁止使用继电器控制&#xff0c;所以需要自己搭建一个mos管控制电路这里使用mos管来驱动GPIO → 电阻(220Ω) → MOSFET栅极(如IRF520N)MOSFET漏极接激光器正极MOSFET源极接地激光器负极直接接电源连接方式如下这里r36为栅极电阻&#xff0c;需要跟你们使用的mos配合…

ubuntu apt源报错?

报错原因&#xff1a;一、网络连接方面1.网络不通畅&#xff08;常见&#xff09;简单来说就是你的虚拟机连不上网&#xff0c;这时候你应该检查自己的ip 是不是dhcp自动获取的&#xff0c;或者你的网络配置是否有误。2.DNS 解析故障&#xff1a;DNS 服务器配置错误或 DNS 服务…

Scene as Occupancy

OccNet https://github.com/OpenDriveLab/OccNet Scene as Occupancy 提出了一种新的场景表示方法&#xff0c; 利用环视摄像头&#xff0c;采用级联和时序体素编码的方式来重建三维Occ场景。Method 1&#xff09;提出的OCCNet首先重建占据描述符&#xff0c;目标是为支持下游任…

Linux基础复习:字符输入与输出

该文仅针对自身对Linux基础知识不足的地方进行补充扩展&#xff0c;便于巩固。终端的输入和输出由字符设备管理。1、查看当前字符设备# 查看当前bash进程 [rootopenEuler-1 ~]# psPID TTY TIME CMD9662 pts/1 00:00:00 bash9938 pts/1 00:00:00 ps# 该目录存放了…

【初识数据结构】CS61B中的基数排序

本教程介绍 CS61B 中的基数排序&#xff0c;这是一种可以在某些情况下甚至超越归并排序、快速排序的特殊的排序方法&#xff0c;但是牺牲了内存空间计数排序 连续编号情形 我们需要对一个编号从 0 到 11 的表进行排序实际上我们可以拿出另一张同样大小的空白表&#xff0c;在遍…

ReAct模式深度解析:构建具备推理能力的AI智能体架构

本文深入剖析ReAct(Reasoning+Acting)架构设计模式,揭示如何通过推理与行动循环构建具备自主决策能力的AI智能体,并展示其在复杂问题求解中的革命性突破。 引言:从工具调用到自主决策的进化 传统AI系统面临的核心瓶颈: #mermaid-svg-orlnKyviyW86xIJZ {font-family:&quo…

Corrosion2靶机攻略

第一步搭建环境 靶机下载地址&#xff1a;https://download.vulnhub.com/corrosion/Corrosion2.ova 下载完成后直接右击用VM打开&#xff0c;重试一下就可以了 右击虚拟机设置将网络连接改成nat模式 第二步信息收集 查看一下靶机的网段&#xff0c;左上角编辑&#xff0c;虚…

SSL 剥离漏洞

一、SSL/TLS 协议基础​1.1、SSL/TLS 协议的核心功能​SSL/TLS 协议的核心功能主要包括三个方面&#xff1a;加密、认证和完整性校验&#xff0c;这三大功能共同构建了网络通信的安全屏障。​&#xff08;一&#xff09;加密​加密是 SSL/TLS 协议最基本的功能。它通过使用对称…

c++-reverse_iterator

C反向迭代器 反向迭代器是C标准库提供的一种适配器&#xff0c;它允许我们以相反的顺序遍历容器&#xff0c;反向迭代器是正向迭代器的封装。 迭代器可以分为两类&#xff1a;方向性质&#xff1a;单向迭代器&#xff08;Forward Iterator&#xff09;双向迭代器&#xff08;Bi…

linux内核驱动:电流/电压/功率监控模块INA226调试

目录背景一、芯片介绍二、手册三、内核驱动配置3.1 设备树配置3.2 修改内核配置文件3.3 编译四、内核驱动分析1、初始化流程2、属性文件/解释五、调试和计算背景 最近调试了一款德州仪器的带有I2C控制接口的可以实现电压、电流、功率监测&#xff0c;并可以进行报警设置的芯片I…

ACL 2024 大模型方向优秀论文:洞察NLP前沿​关键突破

关注gongzhonghao【计算机sci论文精选】近年来&#xff0c;以Transformer架构为核心的大语言模型重塑了自然语言处理领域的技术范式。当前ACL相关研究呈现多维度深化态势&#xff0c;从开源社区推动轻量化架构与低成本训练技术革新&#xff0c;到学术界探索检索增强等机制突破长…

乐创E20H1型IO从站与Ethercat转Profinet网关转换器的配置应用案例

本案例聚焦于西门子 1200PLC 与 E20H1 - T01 IO 从站的连接。在正常运行过程中&#xff0c;E20H1 - T01 IO 从站需支持 EtherCAT 协议&#xff0c;作为 EtherCAT 从站&#xff1b;而监控系统所采用的西门子 S7 - 1200 系列 PLC 则支持 PROFINET 协议。由于协议的不一致性&#…

【2】专业自定义图表创建及应用方法

一、专业自定义图表创建及应用方法1&#xff09;不是图表的图表制作方法例题1:迷你图表制作方法&#xfeff;定义&#xff1a;指依靠Excel基本制图功能之外的其他功能&#xff08;如公式、条件格式、迷你图等&#xff09;创建的数据可视化图表特点&#xff1a;引用数据少且占用…

embodied复现所需docker环境配置粗略流程

由于embodied很多安装包都需要linux环境&#xff0c;所以为了建立虚拟ubuntu系统&#xff0c;在不适用vmvare的情况&#xff0c;可以考虑使用docker容器来实现&#xff0c;也不会出现的vmware的卡顿情况 1.首先建立容器&#xff0c;并和pycharm建立连接,先安装docker desktop&a…