草庐IT

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

coder 2025-02-16 原文

<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 的人有同样的问题。如何解决这个问题?

最佳答案

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

要实现此功能,您需要:

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

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

<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 重新联机时,您可以使用以下命令检查 header :

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: *” header 。

广播

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

Nginx

您可以使用“proxy_set_header”添加额外的 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

激活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 端口的监听器访问您的流。

关于javascript - 由于 CORS 访问限制,MediaElementAudioSource 输出零,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31083704/

有关javascript - 由于 CORS 访问限制,MediaElementAudioSource 输出零的更多相关文章

  1. ruby - 为什么我可以在 Ruby 中使用 Object#send 访问私有(private)/ protected 方法? - 2

    类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc

  2. ruby-on-rails - 由于 "wkhtmltopdf",PDFKIT 显然无法正常工作 - 2

    我在从html页面生成PDF时遇到问题。我正在使用PDFkit。在安装它的过程中,我注意到我需要wkhtmltopdf。所以我也安装了它。我做了PDFkit的文档所说的一切......现在我在尝试加载PDF时遇到了这个错误。这里是错误:commandfailed:"/usr/local/bin/wkhtmltopdf""--margin-right""0.75in""--page-size""Letter""--margin-top""0.75in""--margin-bottom""0.75in""--encoding""UTF-8""--margin-left""0.75in""-

  3. ruby - 检查 "command"的输出应该包含 NilClass 的意外崩溃 - 2

    为了将Cucumber用于命令行脚本,我按照提供的说明安装了arubagem。它在我的Gemfile中,我可以验证是否安装了正确的版本并且我已经包含了require'aruba/cucumber'在'features/env.rb'中为了确保它能正常工作,我写了以下场景:@announceScenario:Testingcucumber/arubaGivenablankslateThentheoutputfrom"ls-la"shouldcontain"drw"假设事情应该失败。它确实失败了,但失败的原因是错误的:@announceScenario:Testingcucumber/ar

  4. ruby-on-rails - 在混合/模块中覆盖模型的属性访问器 - 2

    我有一个包含模块的模型。我想在模块中覆盖模型的访问器方法。例如:classBlah这显然行不通。有什么想法可以实现吗? 最佳答案 您的代码看起来是正确的。我们正在毫无困难地使用这个确切的模式。如果我没记错的话,Rails使用#method_missing作为属性setter,因此您的模块将优先,阻止ActiveRecord的setter。如果您正在使用ActiveSupport::Concern(参见thisblogpost),那么您的实例方法需要进入一个特殊的模块:classBlah

  5. ruby - 通过 erb 模板输出 ruby​​ 数组 - 2

    我正在使用puppet为ruby​​程序提供一组常量。我需要提供一组主机名,我的程序将对其进行迭代。在我之前使用的bash脚本中,我只是将它作为一个puppet变量hosts=>"host1,host2"我将其提供给bash脚本作为HOSTS=显然这对ruby​​不太适用——我需要它的格式hosts=["host1","host2"]自从phosts和putsmy_array.inspect提供输出["host1","host2"]我希望使用其中之一。不幸的是,我终其一生都无法弄清楚如何让它发挥作用。我尝试了以下各项:我发现某处他们指出我需要在函数调用前放置“function_”……这

  6. ruby - 续集在添加关联时访问many_to_many连接表 - 2

    我正在使用Sequel构建一个愿望list系统。我有一个wishlists和itemstable和一个items_wishlists连接表(该名称是续集选择的名称)。items_wishlists表还有一个用于facebookid的额外列(因此我可以存储opengraph操作),这是一个NOTNULL列。我还有Wishlist和Item具有续集many_to_many关联的模型已建立。Wishlist类也有:selectmany_to_many关联的选项设置为select:[:items.*,:items_wishlists__facebook_action_id].有没有一种方法可以

  7. ruby - 如何进行排列以有效地定制输出 - 2

    这是一道面试题,我没有答对,但还是很好奇怎么解。你有N个人的大家庭,分别是1,2,3,...,N岁。你想给你的大家庭拍张照片。所有的家庭成员都排成一排。“我是家里的friend,建议家庭成员安排如下:”1岁的家庭成员坐在这一排的最左边。每两个坐在一起的家庭成员的年龄相差不得超过2岁。输入:整数N,1≤N≤55。输出:摄影师可以拍摄的照片数量。示例->输入:4,输出:4符合条件的数组:[1,2,3,4][1,2,4,3][1,3,2,4][1,3,4,2]另一个例子:输入:5输出:6符合条件的数组:[1,2,3,4,5][1,2,3,5,4][1,2,4,3,5][1,2,4,5,3][

  8. ruby - 将 spawn() 的标准输出/标准错误重定向到 Ruby 中的字符串 - 2

    我想使用spawn(针对多个并发子进程)在Ruby中执行一个外部进程,并将标准输出或标准错误收集到一个字符串中,其方式类似于使用Python的子进程Popen.communicate()可以完成的操作。我尝试将:out/:err重定向到一个新的StringIO对象,但这会生成一个ArgumentError,并且临时重新定义$stdxxx会混淆子进程的输出。 最佳答案 如果你不喜欢popen,这是我的方法:r,w=IO.pipepid=Process.spawn(command,:out=>w,:err=>[:child,:out])

  9. ruby - Ruby 是否使用 $stdout 来写入 puts 和 return 的输出? - 2

    我想知道Ruby用来在命令行打印这些东西的输出流:irb(main):001:0>a="test"=>"test"irb(main):002:0>putsatest=>nilirb(main):003:0>a=>"test"$stdout是否用于irb(main):002:0>和irb(main):003:0>?而且,在这两次调用之间,$stdout的值是否有任何变化?另外,有人能告诉我打印/写入这些内容的Ruby源代码吗? 最佳答案 是的。而且很容易向自己测试/证明。在命令行试试这个:ruby-e'puts"foo"'>test.

  10. ruby-on-rails - 无法在 Rails 助手中捕获 block 的输出 - 2

    我在使用自定义RailsFormBuilder时遇到了问题,从昨天晚上开始我就发疯了。基本上我想对我的构建器方法之一有一个可选block,以便我可以在我的主要content_tag中显示其他内容。:defform_field(method,&block)content_tag(:div,class:'field')doconcatlabel(method,"Label#{method}")concattext_field(method)capture(&block)ifblock_given?endend当我在我的一个Slim模板中调用该方法时,如下所示:=f.form_field:e

随机推荐