APlayer 中文文档 下载 App

音频跨域加载失败的 CORS 问题

现象

控制台出现以下错误之一:

Access to fetch at '...mp3' from origin '...' has been blocked by CORS policy
No 'Access-Control-Allow-Origin' header is present on the requested resource
Media element error: The resource could not be loaded.

或者播放器就是一直转圈加载,不出声。

什么是 CORS

CORS(Cross-Origin Resource Sharing)是浏览器的安全机制。当你的网页(比如 https://example.com)尝试加载另一个域名的资源(比如 cdn-server.com/audio.mp3)时,浏览器会先发送一个预检请求,检查目标服务器是否明确允许跨域访问。

APlayer 会触发跨域的场景

场景是否跨域
网页 https://a.com 加载 your-domain.com/a.mp3❌ 同源,没问题
网页 https://a.com 加载 other-domain.com/a.mp3✅ 跨域,需要 CORS
网页 https://a.com 加载 jsDelivr CDN ...✅ 跨域(但 jsDelivr 支持 CORS)
CDN 不同子域名 static-domain.com vs www-domain.com✅ 不同子域名也算跨域

解决方案一:让音频服务器支持 CORS(推荐)

在音频文件所在服务器的响应头里加上:

Access-Control-Allow-Origin: *

或者更严格地只允许你的域名:

Access-Control-Allow-Origin: your-site.com

具体怎么做取决于你的服务器:

Nginx

location ~* \.(mp3|wav|ogg|m3u8)$ {
    add_header Access-Control-Allow-Origin *;
    # 或者只允许你的域名
    # add_header Access-Control-Allow-Origin your-site.com;
}

Apache (.htaccess)

<FilesMatch "\.(mp3|wav|ogg|m3u8)$">
    Header set Access-Control-Allow-Origin "*"
</FilesMatch>

CDN(jsDelivr / Cloudflare 等)

大多数主流 CDN 已经默认开启了 CORS 支持。如果你用 jsDelivr、cdnjs、unpkg 来分发音频,通常不会遇到跨域问题。

对象存储(阿里云 OSS / 腾讯云 COS / Cloudflare R2)

在控制台里找到 CORS 设置,添加规则允许你的域名或 *。

解决方案二:音频代理到同源

如果音频服务器你控制不了(比如第三方服务、Meting API 返回的 URL),可以通过后端代理来转一下:

// 后端(Node.js Express 示例)
app.get('/audio-proxy', async (req, res) => {
    const targetUrl = req.query.url;
    const response = await fetch(targetUrl);
    const buffer = await response.arrayBuffer();
    res.setHeader('Content-Type', 'audio/mpeg');
    res.send(Buffer.from(buffer));
});

// 前端 APlayer 使用代理 URL
const ap = new APlayer({
    audio: [{
        name: '歌曲名称',
        url: '/audio-proxy?url=' + encodeURIComponent(actualUrl),
        // ...
    }]
});

这样对浏览器来说,请求的是你自己域名下的 /audio-proxy,不会触发跨域。

解决方案三:audio.crossOrigin 属性

APlayer 内部创建的 audio 元素有 crossOrigin 属性。某些场景下设置它能帮到:

// 这不是 APlayer 的参数,需要通过 audio 元素设置
ap.audio.crossOrigin = 'anonymous';

但这需要目标服务器已经正确配置了 CORS,否则还是会失败。

Meting API 场景

Meting API 返回的音频 URL 来自各音乐平台,可能会遇到跨域问题。这不是 APlayer 的问题,而是 Meting API 或目标服务器的限制。

如果用 MetingJS 时遇到跨域,可以:

  1. 尝试换一个音乐平台(网易云不行就换 QQ 音乐)
  2. 自己搭建一个 Meting API 实例并配置好 CORS
  3. 用上面的代理方案

排查步骤

遇到音频加载失败时,按以下顺序排查:

  1. 直接在浏览器地址栏打开音频 URL——能直接播放吗?404?跳转到别的域名?
  2. 打开 DevTools → Network——找到音频请求,查看 Response Headers 里有没有 Access-Control-Allow-Origin
  3. 查看 Console——有没有明确的 CORS 错误提示
  4. 换一个域名测试——把音频放到你自己的服务器上试试能不能播放(如果能,确认是跨域问题)