探索 js 让你的网页“自己开口说话”
最近一直在研究音视频流,正好想要做一个“有声提示”,增强页面交互和用户体验的功能。(以后打算引入前端 AI,让整个页面真正实现“语音控制”,嘿嘿)。这一想,顺便就想到了让一众网友为难的“网页自动播放音视频”。
不说废话,实现过程中倒是遇到了一点小问题:
本来嘛以为是很简单的:就像一般给网页添加背景音乐,先动态创建一个 audio 元素,让其隐藏起来,然后用 js 添加一个 event 事件,并触发(事实上现在普遍认为的是:不能给网页添加背景音乐。但经过猜想和实践发现,也可通过下文第一种解决方式实现):
浏览器厂商为了用户体验考虑禁止自动播放出发点是好的,but 为什么要做这么绝情呢?有一句非常著名的话:“不要试图让用户做自己不熟悉的操作”,难道就不能在
DOMContentLoaded
或者document.readyState==="complete"
前让渲染线程暂停并给出一个显式提示让用户去抉择?你就在 console 里报个错是几个意思
但是这时候发现:浏览器现在全面禁止 audio/video 自动播放了:autoplay 被禁用了! 除非用户主动打开设置
好吧听着就有点匪夷所思,准确地说是——
在 controls 属性存在时 video 允许 autoplay 控制自动播放,controls 不存在时其 autoplay 属性不起作用;(Google)
audio 元素的 autoplay 属性永远不起作用(必须用户手动触发);(Google 和 Firefox)
video 元素是支持 source 兼容的!但是如果 source 中 type 为音频相关格式,那么 autoplay 大概率也不起作用;(Google 和 Firefox 等)
文档中要求的“手动触发”很严格——按道理讲上面代码创建一个鼠标事件其意义和用户手动按下鼠标按钮是一样的,但是,浏览器不支持!
所以我们可以换句话说:mp3 等音频格式的 autoplay 被 Google 禁用了!
没有办法,我只能将目光移向“元素 click 事件”,后来想来是我多想了——因为上面第四点的缘故,任何非用户手动操作的“动作”都会被浏览器禁止。
Google 浏览器为其取了一个很有意义的名字 —— 自动播放阻止。
但是我还是发现了文档中的一个“新”成员:web Audio API。虽然文档中没有描述什么相关原理,但是通过这段描述:
这让我突然的就想到了 HTML5 的另一个“大杀器”:canvas。他也是通过一个上下文对象 context 凌驾于浏览器图像/视频流之上。
web audio api 怎么说呢,感觉至少目前对大多数人用处真不大——文档中 &被广大开发者发掘的各种骚操作 canvas 能做的都用 canvas 了,canvas 不能做的对绝大多数开发者来说也不重要。
顺着这个思路,我想到了“创建一个音轨上下文,在其中用 createBufferSource()
方法用于创建一个新的 AudioBufferSourceNode 接口—— 该接口可以通过 AudioBuffer 对象 来播放音频数据,以突破浏览器限制”,AudioBuffer 对象怎么获取?web audio API 为了解决音频源的问题,提出了“向音频 url 发送一个请求,将数据以 arraybuffer 返回,再解码得到元数据”这样看似复杂的方法,具体过程是这样的:
方法使用 XHR 加载一个音轨,设置请求的 responsetype 为 ArrayBuffer 使它返回一个 arraybuffer 数据,然后存储在 audioData 变量中。然后我们将这个 arraybuffer 数据置于 decodeAudioData()方法中使用,当成功解码 PCM Data 后通过 promise 回调返回, 将返回的结果通过 AudioContext.createBufferSource()接口进行处理并获得一个 AudioBufferSourceNode,,将源连接至 AudioContext.destination 形成一个完整的音频流。
这里有两个注意点:
倒数第六行 url 那里如果是个音频的话最好还是手动下载到本地,不然极有可能涉及到跨域问题
如果是要“语音提示某一段话”,则可以为代码中
init()
函数增加 txt 参数,并调用百度转化接口,将文字先用 encodeURI API 转化为 uri 格式,再接入百度接口var url = "http://tts.baidu.com/text2audio?lan=zh&ie=UTF-8&text=" + encodeURI('这里是字符串文本');
转化为 url 链接
这段代码很神奇:google 不支持,但是控制台里面“万恶的报错”也没有了,会给你一个提示:
总之就是我不给你播放。
所以,在除了 Google 的其余浏览器中,建议将上面的 API 和下面这段 HTML 代码一起写上:
然后你应该就可以听到美妙动听的背景音了!
Firefox 和 Edge 虽然禁掉了 autoplay,但是它也是支持 AudioContext API 的!Google 中禁止了一切不符合规范的 API,而且可能是因为某些不知名原因,上面这段 HTML 代码在 Google 中是时而可以时而不行的,就很迷惑。。。
补充其实这个 API 最大的作用是用于音频可视化领域——它有一个函数是这样的:createAnalyser()
用来创建一个音域可视化对象,可以将它连接到 context 流上:
发现浏览器中有了部分实现的相关 API——它曾经一直在逃避浏览器音频播放政策:
参数 sentence 是一个字符串格式文本。
只要调用了这个函数并传入参数,你就能在浏览器中听到动听的、梦寐以求的声音了!(还是个女声,嘿嘿嘿)目前,Chrome70 已经废弃这个 API 了。。。(因为它可以不经过用户主动触发而直接播放)
当然还有稳妥一些的做法,也是个让人比较眼前一亮的操作:是 MDN 文档中提到的 Feature-Policy
头——HTTP 头信息,可设置自动播放相关:这个属性是给后端用的:在 response 中设置 header!
版权声明: 本文为 InfoQ 作者【云小梦】的原创文章。
原文链接:【http://xie.infoq.cn/article/0046baa56d4a1ba22cd15b2ec】。文章转载请联系作者。
评论 (2 条评论)