Notification 语音播放

2,007 阅读2分钟

前言

准备做web端的消息通知, 通过Notification 做系统消息的弹框,发现自动播放声音问题。 出于好奇对W3C 关于 autoplay 例子进行参考... 更多可参考github链接,更多消息提示demo

关于audio自动播放问题

  // 此代码可以放入 source 面板 Snippets 中运行, 不要放入控制台去运行, 控制台可以直接播放, 因为涉及鼠标回撤键, 鼠标事件,触发执行。
  let audio = document.createElement('audio');
  audio.autoplay="autoplay";
  audio.meted = false;
  audio.src = 'http://127.0.0.1:3003/notice_test.mp3';
  audio.play(); 

  // Uncaught (in promise) DOMException: play() failed because the user didn't interact with the document first.

发现谷歌浏览器在高版本中禁用 声音的自动播放问题,必须人为的去触发事件, 鼠标事件或键盘事件等还有控制台, 直接执行上面代码会直接报错

在w3c 网站上去查看audio autoplay 属性时, 发现点击链接打开页面可以进行自动播放。 但刷新页面时, 不会再次播放。 还有一个规律就是, 只要首次播放了声音, javascript 代码就可以完成上述代码的直接播放。 出于好奇, 模拟了w3c代码实现, 代码如下

# 涉及表单提交 启动服务
npx http-server . -p $port
  • index.html
  <form id="codeForm" autocomplete="off" style="margin:0px;display:none;" action="/b.html" method="get" accept-charset="utf-8" target="iframeResult">
      <input type="hidden" name="code" id="code" value=""/>
  </form>
  <div id="iframecontainer"> 
    <div id="iframe">
         <div id="iframewrapper">
        <iframe frameborder="0" id="iframeResult" name="iframeResult"></iframe>
      </div>
    </div>
  </div>
  <script>
    submitTryit();

    function submitTryit() {
        if (window.editor) {window.editor.save();}
        let text = document.getElementById("textareaCode").value;

        let ifr = document.createElement("iframe");
        ifr.setAttribute("frameborder", "0");
        ifr.setAttribute("id", "iframeResult");
        ifr.setAttribute("name", "iframeResult");  
        document.getElementById("iframewrapper").innerHTML = "";
        document.getElementById("iframewrapper").appendChild(ifr);

        let  t = text;
        t=t.replace(/=/gi,"w3equalsign");
        t=t.replace(/\+/gi,"w3plussign");

        //document.write(t);
        var pos=t.search(/script/i);

        while (pos>0) {
          t=t.substring(0,pos) + "w3" + t.substr(pos,3) + "w3" + t.substr(pos+3,3) + "tag" + t.substr(pos+6);
          pos=t.search(/script/i);
        }

        document.getElementById("code").value=t;
        document.getElementById("codeForm").action = "/b.html";
        document.getElementById('codeForm').method = "get";
        document.getElementById('codeForm').acceptCharset = "utf-8";
        document.getElementById('codeForm').target = "iframeResult";
        document.getElementById("codeForm").submit();
    }
  </script>
  • b.html
    <audio controls="controls" autoplay="autoplay">
        <source src="/1702.mp3" type="audio/mpeg"/>
    </audio>

w3c 例子其实a链接打开新标签的时候 鼠标事件被传递到新开的标签, 因此form表单自动提交, iframe 嵌入b.html 完成的自动播放。 页面刷新时不会自动播放, 如果javascript 直接执行auto.play() 则会报错。 关于audio 播放问题, google 一下, 暂时还没找出更好的办法, 据说可以hack 但出于见识, 不知道具体的实施方案。如有大牛,可以给出试例。

github链接