为不同的浏览器开发音频播放器时可以学到什么

这个故事始于1.5年前。 它与在运行它们的各种浏览器和平台上播放音乐相关联。 充满“痛苦和痛苦”的道路使人们意识到,乍看之下容易完成的任务可能并不那么容易,而一开始就不重视的“无关紧要”的细节会影响到一切。

最好奇的小细节:)
1.从网络下载有关每个下一曲目的数据。
2.对于音频的每个元素:新的Audio()或<audio>,您需要用户的许可-页面上的用户操作。

背景知识


大概每个曾经为浏览器编写过音频播放器的人一生中都遇到了跨浏览器兼容性和跨平台的问题。

因此,在开发新的MVP时,我遇到了有关在浏览器中播放音频的各种功能。

一切都始于在播放过程中必须平滑地淡化两个音轨的事实-这是第一个功能。 我们的团队希望更改广播中的曲目。 第二个功能-从网络请求每个后续轨道。



研究成果


然后,几乎我们所有的项目都使用了Sound Manager 2库。

几乎立即,您意识到在移动设备上同时播放两个音频文件在任何地方都无法正常工作!

在PC的Chrome浏览器(〜62版)中,按需播放曲目。 在移动设备上(在Chrome中也是如此),曲目播放有效,但只能在屏幕处于活动状态时进行。 屏幕锁定时,当前播放器之后的下一首曲目未播放。 至于iOS / macOS,播放方式也类似。 可以在此处获得更多信息-“单个音频流”部分。

因此,我们开始走过三海寻找点点滴滴的有关带有音频的浏览器功能的信息。

好的,我正在尝试不使用任何库的Web Audio解决方案。 是的,该技术还用于其他目的:合成,声音处理,游戏等,而不是简单地播放曲目。 但是为了进行实验,有必要尝试一下,因为它可以让您将来自不同来源的声音合成为一个音频输出 -扬声器/耳机/电话扬声器等。 有些人专门研究使用Web Audio API在移动设备上播放声音可能性。

实施后,某些细微差别变得清晰。

首先,您必须等待直到整个曲目都已满载。 Internet连接速度较慢时,由于第二条曲目可能在第一条曲目结束时可能没有时间加载,因此会引起明显的暂停。 可以使用大量HTML5音频标签来避免完全下载,这些标签将用作Web音频的声音源,但是在这种情况下,再次播放两个声音就变得不可能了。

其次,如果您通过网络下载片段中的轨道并以编程方式对其进行解码,则会增加CPU的负担。 对于PC而言,这是可以接受的,但对于移动设备而言,则至关重要。

第三,解码存在问题。 如果mp3 / ogg / wav文件的片段到达客户端,则这些片段将被悄悄解码并播放。 但是,如果充当HE-AAC容器的mp4文件的大部分进入了浏览器,则它们将无法解码。 这在某种程度上也适用于Opera浏览器,在该浏览器中,MP3文件的播放在各个版本之间都是不稳定的-有时会重现,并且会出现一个错误,指出不支持此格式。

第四,在带有本机音频播放器(在iPad上)的平板电脑上的锁定屏幕上,曲目名称未显示/未更改,包括。 在曲目之间切换时。 也许是由于测试使用的iPad是iOS 9版本-当时没有其他产品了。

结果,在此阶段,必须放弃Web Audio。 尽管如此,crossfade并不适合浏览器,高质量的标准音乐作品占了很大的比重。

由于我们拒绝交叉淡入淡出,因此我们分别在音乐曲目的开头和结尾处实现了简单的淡入和淡出。

前一年中的代码已稍作修改和测试。 测试的结果浮出水面(表中所示)。 所有这些都使用Sound Manager 2库。



我们添加所有事件的日志记录,以确定曲目之间的过渡时刻,并了解它们在何时停止播放。



标签激活
在Safari 9+中,激活选项卡时声音并不总是出现。

据此可以假定JS在后台执行受到限制,或者执行线程完全停止(事件和计时器 )。 但是,稍后将变得很清楚,这部分是正确的结论。 下面,我们将考虑与播放曲目相关的另一种细微差别,并理解为什么声音不出现。

备注
若要处理进度(progressbar),例如将其渲染为轨道,最好使用requestAnimationFrame而不是setInterval / setTimeout。 您可以避免在取消激活(背景选项卡),然后激活该选项卡并将其暂时冻结(与所有计算相关联并重新绘制进度状态)时产生累积效应。

同时,出现了一个问题:如何在PC和移动设备上自动播放曲目?
自动播放是指在加载页面时无需任何用户操作即可自动开始播放曲目。
对于Safari,有关页面加载时的自动播放 ,这是不可能的,您需要用户与页面进行交互 ,就像在移动设备上一样 。 这适用于视频内容音频内容

因此,当时存在以下情况:

  1. 不可能(不希望)同时再现两个或多个声音;
  2. 对于曲目的伪“自动播放”,需要用户许可-第一次交互,后来被称为“向设备出售一根手指”;
  3. 在后台(背景标签/锁定屏幕)JS(取决于浏览器):
    要么完全冻结;要么
    节流
    两者的作用与活动选项卡相同;
  4. 您可以自动开始无声音播放,但不清楚为什么(对于音频内容)?
  5. 某个遥远的地方开始浮现思想,但是如何使JS在后台继续执行?

其他实现播放器功能的库都假设可能有解决此问题的方法。 尽管在GitHub上观看了很多问题并在各种浏览器中播放曲目时描述了问题,但仍然希望您能深入了解:为什么不起作用以及如何使其起作用。 事实证明,没有...

带有库工作视频演示的一些代码示例:

  1. 声音管理器2- github页面github存储库 ,视频: macOS Safari 12 ; 屏幕解锁的iOS Safari 10
  2. ler叫
    咆哮v2.0.9- github页面github存储库 ,视频: macOS Safari 12iOS Safari 10
    Howler v2.0.15- github页面github存储库 ,视频: macOS Safari 12
    咆哮v2.1.1- github页面github存储库 ,视频: macOS Safari 12iOS Safari 10

对于macOS,视频录制时没有声音,因此您需要查看音量指示器-选项卡上扬声器的图像。

存储库中提供了更多示例视频。

在Howler v2.1.1的交互式示例中-有时您可以同时听到几种声音,这是由于添加了由用户解锁的音频元素池(此问题将在以后的库版本中修复)。
这些库无法操作的原因是什么?

我在上面写道: “在后台(“后台”选项卡),JS要么完全冻结,要么受到限制 因此,这里弹出了另一点:代码中的库使用通过新的Audio()创建新的音频对象。 如果它们是动态创建的,即 如果未使用现有的音频对象,并且用户没有以任何方式与站点进行交互,选项卡处于禁用状态或屏幕被锁定,则某些浏览器可能会认为,除非选项卡再次处于激活状态,否则不应播放此音频元素的声音,否则用户不会任何行动。

使用新的Audio()在github页面github上的存储库中的示例测试。 视频: macOS Safari 12 ; 屏幕解锁的iOS Safari 10

似乎不存在某种通用工具,因此有必要寻找其他妥协解决方案。

然后,我们与团队的成员坐下来讨论,在音频播放器的工作中真正重要的是什么? 因为可以无限地继续进行实验,但是我们需要继续前进。

首先,确定了阻碍实现预期结果的要点:

  1. 选项卡处于非活动状态时,macOS上的Safari不会播放曲目;
  2. 在运行iOS和Android的智能手机上,不可能在后台(屏幕锁定时)听音乐,我希望避免(将来)将用户积极地重定向到移动应用程序,因为以前的经验表明,相当一部分用户不想安装移动应用程序;
  3. 播放器无法正确处理动态播放列表,即 如果事先不知道下一首曲目是什么。

此外,它允许制定实现以下目标所需的目标:

  1. 在各种浏览器和各种平台上提供后台播放器;
  2. 允许用户选择使用什么:在网站上或在移动应用程序中听音乐;
  3. 提供在未来的各种项目中使用播放器(或方法)的能力。

寻找解决问题的新阶段已经开始。 在此阶段,不再使用各种库;所有研究都是使用HTML5 Audio进行的。 结果是使用专职工作人员找到了一个选项。 iOS不允许该决定再次获胜-在后台播放无法正常工作,但事实证明该操作适用于Android(Chrome,Opera,Safari)。

在github页面github存储库 HTML5 Audio + Dedicated Workers测试示例。

初始化Worker后,将请求有关当前轨道的数据。 工作者还发送信号以从主流获取进度状态(轨道播放多长时间),并根据该数据决定何时从网络请求有关下一轨道的数据。



同样在那时,当HTML5音频标签嵌入DOM(视频: macOS Safari 12iOS Safari 10 )中时,下面的示例( github页面github 存储库 )经过了测试,当在音轨之间切换时,它仅替换了SRC。 迄今为止,此示例在12 Safari中的macOS上有效。 不幸的是,现在无法在Safari 10和11的macOS上测试此示例的功能,但当时该示例在测试期间不起作用( 自动播放策略自动播放限制 )。

总而言之,对于iOS和macOS,如果是在事件(例如ajax,setTimeout,onended)中在后台创建的,则Safari浏览器不会考虑用户激活音频元素的新实例。

此外,关于在iOS Safari和iOS Chrome中播放曲目的问题,发现可以仅使用HLS在后台(锁定屏幕时)播放曲目。 对于iOS和macOS平台,此格式是标准格式,并且操作系统支持广播。 对于Android Chrome和Edge,也可以使用本机实现。 对于Chrome中的PC,您可以使用软件处理程序,例如hls.jsBitmovin Player等。

到github存储库的链接提供了涵盖最简单用例的代码示例-仅播放服务器上生成的流,而无法倒带,切换到下一首曲目等。 使用以下示例显示示例:音频标签,视频标签,hls.js库和Bitmovin中的播放器。 此内容需要Node.js。

结论


不幸的是,第一点是,由于浏览器的种类繁多,没有一种通用的解决方案可以使浏览器在任何地方都能很好地听音乐。 在任何地方都有局限性,并且如实践所示,您可以相当舒适地生活在其中。

第二点,有时值得尽快检查边界情况,例如本机实施。 查找某种最低限度可接受的需求集,并快速检查其性能,而不是以任何库为基础。 这将使您更多地了解这些库是如何内部排列的以及某些功能为何起作用或不起作用。 否则,您会在项目中运行很长时间,并且在意识到有问题之后。 事实证明,放弃图书馆将是非常昂贵的。 该代码的很大一部分将需要重写。

第三点,请务必注意您的服务的受众-用户来自哪个浏览器和操作系统。 使用各种度量标准和错误监视系统,这非常容易跟踪。 这样的方法将有助于了解支持哪些平台和浏览器很重要,以及可以不费吹灰之力地使用哪些平台和浏览器。

最后


我宣布了一个与使用HLS技术在iOS上播放音乐有关的小型竞赛。

可以在github上的链接上看到描述。

Source: https://habr.com/ru/post/zh-CN438952/


All Articles