页面加载完了,网站播放器按钮也亮了,声音点下去——没声。网站进度条在走,声音频谱图在跳,网站唯独音箱安静得像块砖。声音这事我上周刚遇上,网站一个在线白噪音网站,声音想用它盖住楼下装修的网站电钻声,结果自己先被静音了。声音
先查本地。网站系统音量没关,声音浏览器标签页没静音,网站耳机插在主机后面板上——拔下来换到前面板,声音还是网站没声。打开另一个视频网站,声音正常。说明问题不在硬件,也不在系统。回到那个白噪音网站,右键查看页面源代码,找到<audio>标签,src指向一个.mp3文件。直接复制链接在新标签页打开,浏览器弹出一个内置播放器,点播放,出声了。
这就怪了。同一个文件,直接访问能播,嵌在页面里就没声。打开开发者工具,切到Network面板,刷新页面,看那个mp3的请求状态——200 OK,但Content-Type响应头写的是text/html。服务器把音频文件当网页返回了。浏览器拿到一个MIME类型不对的响应,<audio>元素直接放弃解码,连报错都懒得报。
这种问题在个人站点上不算少见。有人用对象存储传文件,上传时没指定Content-Type,默认给了application/octet-stream或者干脆继承上一层的text/html。浏览器对<audio>和<video>的MIME类型检查比<img>严格得多——图片嗅探一下还能显示,音频嗅探失败就彻底沉默。Chrome的控制台里其实有警告,但默认过滤级别下根本不显示,得手动把Verbose打开才能看见一行灰色小字:Failed to load because no supported source was found。
另一个常见坑是自动播放策略。有些网站把autoplay属性挂在<audio>上,以为能像以前那样一打开就响。Chrome从66版开始就禁止了带声音的自动播放,除非用户跟页面有过交互——点击、触摸、按键都算。没交互就自动播的,play()返回的Promise会reject,控制台报NotAllowedError。开发者如果没写.catch(),这个错误就悄无声息地吞掉了。用户看到播放按钮是亮的,以为在播,其实音频上下文压根没启动。
我见过更隐蔽的一种:Web Audio API的AudioContext在页面加载时创建,但没在用户手势事件里resume()。状态一直是suspended,所有通过createBufferSource或者decodeAudioData播放的声音都出不来。这种问题在那些用Web Audio做可视化或者游戏音效的站点上特别多。开发者本地测试时可能点过页面,上下文恢复了,一切正常。用户直接打开,没点任何东西,就静音。
回到那个白噪音网站。我在Network面板里右键那个mp3请求,选择"Copy as cURL",贴到终端里跑,看完整响应头。果然,Content-Type: text/html; charset=utf-8。服务器是nginx,配置里大概有个location ~* \.(mp3|ogg|wav)$的块,但types指令没包含audio/mpeg,或者被更宽泛的location /规则覆盖了。改起来倒简单,加一行types { audio/mpeg mp3; },重载nginx,刷新页面,声音出来了。
电钻声还在响,但至少现在我能用白噪音盖住它了。网站没声音这事,九成出在服务端配置或者浏览器策略上,剩下一成是用户自己静音了标签页还忘了。排查顺序别搞反:先看Network里的MIME类型,再看Console里的自动播放报错,最后才去翻系统音量。