由于 CORS 访问限制,MediaElementAudioSource 输出零

Posted

技术标签:

【中文标题】由于 CORS 访问限制,MediaElementAudioSource 输出零【英文标题】:MediaElementAudioSource outputs zeroes due to CORS access restrictions 【发布时间】:2015-09-14 00:41:38 【问题描述】:
<script>
// Create a new instance of an audio object and adjust some of its properties
var audio = new Audio();
audio.src = 'http://subdomain.domain.org:port/;stream/1';
audio.controls = true;
audio.loop = true;
audio.autoplay = true;
audio.crossorigin="anonymous";
// Establish all variables that your Analyser will use
var canvas, ctx, source, context, analyser, fbc_array, bars, bar_x, bar_width, bar_height;
// Initialize the MP3 player after the page loads all of its html into the window
window.addEventListener("load", initMp3Player, false);
function initMp3Player()
    document.getElementById('audio_box').appendChild(audio);
    context = new (window.AudioContext || window.webkitAudioContext)(); // AudioContext object instance // AudioContext object instance
    analyser = context.createAnalyser(); // AnalyserNode method
    canvas = document.getElementById('analyser_render');
    ctx = canvas.getContext('2d');
    // Re-route audio playback into the processing graph of the AudioContext
    source = context.createMediaElementSource(audio);
 source.crossOrigin = 'anonymous'   
    source.connect(analyser);
    analyser.connect(context.destination);
    frameLooper();

// frameLooper() animates any style of graphics you wish to the audio frequency
// Looping at the default frame rate that the browser provides(approx. 60 FPS)
function frameLooper()
    (requestAnimationFrame || webkitRequestAnimationFrame)(frameLooper);
    fbc_array = new Uint8Array(analyser.frequencyBinCount);
    analyser.getByteFrequencyData(fbc_array);//get frequency

    ctx.clearRect(0, 0, canvas.width, canvas.height); // Clear the canvas
    ctx.fillStyle = '#00CCFF'; // Color of the bars
    bars = 100;
    for (var i = 0; i < bars; i++) 
        bar_x = i * 3;
        bar_width = 2;
        bar_height = -(fbc_array[i] / 2);
        //  fillRect( x, y, width, height ) // Explanation of the parameters below
        ctx.fillRect(bar_x, canvas.height, bar_width, bar_height);
    

</script>

由于 CORS 访问限制,音频 API 将 MediaElementAudioSource 输出为零,因为我正在尝试播放 SHOUTcast URL。我不知道该怎么办;我已经尝试了互联网上的所有解决方案,但没有任何效果。任何帮助将不胜感激。

URL 与音频元素完美配合,因此与 URL 无关;我什至尝试过http://subdomain.domain.org:port/file.mp3 之类的东西。我在互联网上发现使用 .ogg 的 Icecast 的人也有同样的问题。如何解决这个问题?

【问题讨论】:

我在使用我正在试验的一支笔时遇到了 codepen.io 这个问题。有什么建议吗? 对不起,我想投票,我点击了向下按钮,所以不会让我改变它.. 【参考方案1】:

这是一个 HTTP 标头。您将配置您的网络服务器或网络应用程序以发送此标头。也许在 htaccess 或 php 中。删除下面的行

    <header name = "Access-Control-Allow-Origin" value = "*" />

【讨论】:

所以我把
放在我的代码同一目录中的 .htaccess 文件中?这就是你的意思?
如果需要使用您使用的任何服务器语言配置您的标头。大多数服务器都允许使用 php,因此您可以尝试: 我已经试过了 我对 cors 不太熟悉,但现在您请求的站点(称为站点 b)必须发送:Access-Control-Allow-Origin as先。因此,仅设置您自己的标题将无济于事。您需要联系网站管理员,看看他们是否会发送该邮件。我相信当你在本地工作时,自己设置是件好事 我是该网站的管理员.. 网络 (apache) 和同一个 linux 服务器上的直播。但是如果我有访问权限,我该如何解决?【参考方案2】:

SHOUTcast 服务器不支持 CORS。如果您要继续使用 SHOUTcast,则无法更改此设置。

【讨论】:

我做了一些事情,但感觉不对。我在播放器的同一目录中制作了一个代理脚本并播放了这个脚本 @user1531557 是的,如果您使用的是 SHOUTcast,这是唯一的方法。这是一种常用的方法。为此,我实际上创建了自己的流媒体服务器。如果您想尝试,请发送电子邮件至 brad@audiopump.co。我正在努力在今年晚些时候推出一项托管服务,但它现在已经以有限的容量启动并运行了。【参考方案3】:

首先,MediaElementAudiosource 没有名为“crossOrigin”的属性。

我只是发现了这个问题,并且对 Message:MediaElementAudioSource 由于 CORS 访问限制而输出零感到愤怒。但这只是一条消息,我仍然可以听到音频。 我用谷歌搜索了很多,认为这个链接会有所帮助:http://www.codingforums.com/javascript-programming/342454-audio-api-js.html

createMediaElementSource 方法应该创建一个使用 MediaElementAudioSourceNode 接口的对象。此类对象受基于 Web 音频 API 规范最新草案的跨域资源共享 (CORS) 限制。 (请注意,此限制似乎不在规范的过时 W3C 版本中。)根据规范,当 CORS 限制阻止对资源的访问时应该播放静音,这将解释“输出零”消息;据推测,零相当于没有声音。

要解除限制,页面的所有者位于 http://morebas-s-radio.no-ip.org:8214/;stream/1 需要配置 他们的服务器输出一个 Access-Control-Allow-Origin 标头 域列表(包括您的域)或用于提升它的 * 值 对于所有域。鉴于此流似乎已经 不受限制的,面向公众的内容,也许您可​​以说服所有者 输出该标题。您可以测试是否正在发送标头 通过在 Firefox 中按 Ctrl+Shift+Q 打开 Network 面板,加载 通过地址栏的流,然后检查标题 在“网络”面板中与该 HTTP 请求相关联。

请注意,他们不能在这里使用元元素,因为音频流 显然,它不是 HTML 文档;该技术仅适用于 HTML 和 XHTML 文档。

(当您在使用 Firefox 面板时,您可能需要确保 启用安全错误和警告(通过单击安全 按钮或其箭头)在控制台面板 (Ctrl+Shift+K)。我不知道 如果 Firefox 中像 Chrome 一样有相应的 CORS 消息,但是 可能有。我浪费了很多时间想知道为什么页面没有 一天工作,同时对类似技术进行故障排除,内容 安全策略(CSP),才发现我有相关的火狐 消息已隐藏。)

您不需要弄乱跨域属性/属性 除非您设置 crossorigin = "use-credentials" (JavaScript) 或 crossorigin="use-credentials" (HTML) 某处,但你可能 没有这样做是因为 HTML 规范的那部分还没有最终确定, 它几乎肯定会导致您的内容在之后“中断” 这样做是因为那时需要凭据。

我不熟悉 Web Audio API,所以我无法弄清楚 找出如何输出 MediaElementAudioSourceNode 并触发错误 我自己的故障排除消息。如果我使用 createMediaElementSource 使用 HTMLMediaElement (HTMLAudioElement),结果似乎没有 成为基于使用测试的 MediaElementAudioSourceNode instanceof 运算符,即使规范说如果我是 没看错。

然后在我的情况下,我得到了 HTTP 响应标头:

HTTP/1.1 206 Partial Content
Date: Thu, 02 Jun 2016 06:50:43 GMT
Content-Type: audio/mpeg
Accept-Ranges: bytes
Access-Control-Allow-Origin: *
Access-Control-Expose-Headers: X-Log, X-Reqid
Access-Control-Max-Age: 2592000
Content-Disposition: inline; filename="653ab5685893b4bf.mp3"
Content-Transfer-Encoding: binary
Last-Modified: Mon, 16 May 2016 02:00:05 GMT
Server: nginx
Cache-Control: public, max-age=31536000
ETag: "FpGQqtcf_s2Ce8W_4Mv6ZqSVkVTK"
X-Log: mc.g;IO:2/304
X-Reqid: 71cAAFQgUBiJMVQU
X-Qiniu-Zone: 0
Content-Range: bytes 0-1219327/1219328
Content-Length: 1219328
Age: 1
X-Via: 1.1 xinxiazai211:88 (Cdn Cache Server V2.0), 1.1 hn13:8 (Cdn Cache Server V2.0)
Connection: keep-alive

请注意“Access-Control-Allow-Origin: *”,我认为这是正确的,但我仍然收到消息。希望对你有帮助。

【讨论】:

【参考方案4】:

在我的回复中,我将假设以下设置:

您的直播网址是 http://stream.radio.com:8000/mount(或 http://stream.radio.com:8000/;stream/1 用于 Shoutcast) 放置 HTML/JS 代码的页面 URL 是 http://radio.com/player

要完成这项工作,您需要:

    将流的“Access-Control-Allow-Origin”标头设置为您的域或* 在javascript中,将audio标签crossOrigin属性设置为“匿名”audio.crossOrigin="anonymous"; 另一个选项是使用反向代理将您的流式 URL 移动到原始域。

使用Icecast,您可以使用配置文件设置“Access-Control-Allow-Origin”标头,只需将以下行添加到您的icecast.xml,我通常在打开后添加它们@ 987654329@标签:

<http-headers>
        <header name="Access-Control-Allow-Origin" value="*" />
        <header name="Access-Control-Allow-Headers" value="Origin, Accept, X-Requested-With, Content-Type, If-Modified-Since" />
        <header name="Access-Control-Allow-Methods" value="GET, OPTIONS, HEAD" />
</http-headers>

在进行这些更改后不要忘记重新启动 Icecast。当您的 Icecast 重新上线时,您可以使用以下命令检查标题:

lynx -head -dump http://stream.radio.com:8000/mount 

响应应如下所示:

Server: Icecast 2.4.2
....
Access-Control-Allow-Origin: *
Access-Control-Allow-Headers: Origin, Accept, X-Requested-With, Content-Type, If
-Modified-Since
Access-Control-Allow-Methods: GET, OPTIONS, HEAD

如您所见,存在“Access-Control-Allow-Origin: *”标头。

大喊大叫

不幸的是,Shoutcast 不允许您设置 HTTP 标头(.htaccess 也不是一个选项),但我们可以在 Web 服务器配置中创建一个反向代理,这将允许您托管来自主域的流 - @ 987654333@。我将为 Nginx 和 Apache 提供代理配置。

Nginx

您可以使用“proxy_set_header”添加其他标头,但基本示例是:

server 
    listen   80;
    server_name radio.com;
    ....
    location /stream  
       proxy_set_header X-Forwarded-For $remote_addr; 
       proxy_pass http://stream.radio.com:8000/mount; 
    
    ....

阿帕奇

激活 Apache 代理模块,并更新 radio.com 虚拟主机配置配置:

<VirtualHost *:80>
   ServerName radio.com
   ....
   ProxyPass /stream http://stream.radio.com:8000/mount
</VirtualHost>

现在您可以使用http://radio.com/stream URL 访问您的流媒体,CORS 政策将不适用。此解决方案还带来了一些额外的好处:

您可以将 http Shoutcast/Icecast 流转换为 https,因此当您将流嵌入到使用 https 托管的页面时,浏览器不会抱怨访问不安全的内容。 (Icecast 本身支持 SSL 配置) 8000 端口将被替换为 80 端口,这将允许具有 8000 端口在防火墙后面的侦听器访问您的流。

【讨论】:

以上是关于由于 CORS 访问限制,MediaElementAudioSource 输出零的主要内容,如果未能解决你的问题,请参考以下文章

由于 CORS 访问限制本地 mp3 文件,MediaElementAudioSource 输出零

跨域访问CORS探究

AJAX跨域调用相关知识-CORS和JSONP

由于 CORS 限制,无法使用 firebase 在本地进行测试

如何使用 CORS 限制 AWS S3 访问?

Java服务端用CORS方法解决浏览器跨域问题