将音频从 youtube 流式传输到 html 音频标签
Stream audio from youtube to an html audio tag
我使用一个名为 youtube-audio-stream 的库,该库使用 fluent-ffmpeg 和 ytdl-core,以便从给定的 youtube link 接收可读流,然后将其通过管道传输到响应对象并使用我的快速服务器的端点作为我 html 页面中音频标签的源。
每当我加载 html 页面并尝试点击播放时,都会出现以下错误:
events.js:467
function arrayClone(arr, n) {
^
RangeError: Maximum call stack size exceeded
at arrayClone (events.js:467:20)
at PassThrough.emit (events.js:196:23)
at PassThrough.output.on.error (C:\development\ElectronTut\ytmp3\node_modules\youtube-audio-stream\index.js:38:16)
at PassThrough.emit (events.js:198:15)
at PassThrough.output.on.error (C:\development\ElectronTut\ytmp3\node_modules\youtube-audio-stream\index.js:38:16)
at PassThrough.emit (events.js:198:15)
at PassThrough.output.on.error (C:\development\ElectronTut\ytmp3\node_modules\youtube-audio-stream\index.js:38:16)
at PassThrough.emit (events.js:198:15)
at PassThrough.output.on.error (C:\development\ElectronTut\ytmp3\node_modules\youtube-audio-stream\index.js:38:16)
at PassThrough.emit (events.js:198:15)
经过几个小时的研究,我终于放弃了,来到了这里。据我了解,当调用堆栈在下一个进程开始之前没有正确清空时会触发此错误,大多数 Whosebug 论坛一直在讨论异步编程如何导致潜在的无限循环,但我没有搞砸几乎没有足够的地方来理解流中可能发生这种循环的地方。
这是我的服务器代码:
const express = require("express");
const app = new express();
const stream = require('youtube-audio-stream');
const uri = "https://www.youtube.com/watch?v=t1TcDHrkQYg";
app.get("/audio", (req, res) => {
stream(uri).pipe(res);
})
app.listen(3000, () => console.log("Ready!"))
我的前端代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Doc</title>
</head>
<body>
<audio autoplay controls>
<source src="http://localhost:3000/audio" type="audio/mpeg">
</audio>
</body>
</html>
如果这听起来很愚蠢或者我做了一些愚蠢的事情,我深表歉意,但我真的处于边缘并且失去了所有希望。我将如何解决或处理这个范围错误?
如果您愿意,请问任何做过与我正在做的事情类似的人,还有更好的选择吗?
非常感谢您的时间和精力。
已修复,糟糕的库使用的是 ytdl-core 的过时版本!我下载了youtube-audio-stream的源码,然后把ytdl-core更新到最新版本,现在一切正常了!
这是一个没有 server-side 的解决方案。
我(也)花了几个小时试图让这个工作...
在看到您的 post 后,我调查了 youtube-audio-stream
,但我一直没有成功。相反,我最终得到了这个似乎运行良好的解决方案。阅读 this post 后,我修改了一些值以适应 YouTube 当前 (2020) API。
这是一个应该有效的解决方案,适合任何正在寻找的人! Try on CodePen
// YouTube video ID
var videoID = "CMNry4PE93Y";
// Fetch video info (using a proxy if avoid CORS errors)
fetch('https://cors-anywhere.herokuapp.com/' + "https://www.youtube.com/get_video_info?video_id=" + videoID).then(response => {
if (response.ok) {
response.text().then(ytData => {
// parse response to find audio info
var ytData = parse_str(ytData);
var getAdaptiveFormats = JSON.parse(ytData.player_response).streamingData.adaptiveFormats;
var findAudioInfo = getAdaptiveFormats.findIndex(obj => obj.audioQuality);
// get the URL for the audio file
var audioURL = getAdaptiveFormats[findAudioInfo].url;
// update the <audio> element src
var youtubeAudio = document.getElementById('youtube');
youtubeAudio.src = audioURL;
});
}
});
function parse_str(str) {
return str.split('&').reduce(function(params, param) {
var paramSplit = param.split('=').map(function(value) {
return decodeURIComponent(value.replace('+', ' '));
});
params[paramSplit[0]] = paramSplit[1];
return params;
}, {});
}
<audio id="youtube" controls></audio>
我使用一个名为 youtube-audio-stream 的库,该库使用 fluent-ffmpeg 和 ytdl-core,以便从给定的 youtube link 接收可读流,然后将其通过管道传输到响应对象并使用我的快速服务器的端点作为我 html 页面中音频标签的源。
每当我加载 html 页面并尝试点击播放时,都会出现以下错误:
events.js:467
function arrayClone(arr, n) {
^
RangeError: Maximum call stack size exceeded
at arrayClone (events.js:467:20)
at PassThrough.emit (events.js:196:23)
at PassThrough.output.on.error (C:\development\ElectronTut\ytmp3\node_modules\youtube-audio-stream\index.js:38:16)
at PassThrough.emit (events.js:198:15)
at PassThrough.output.on.error (C:\development\ElectronTut\ytmp3\node_modules\youtube-audio-stream\index.js:38:16)
at PassThrough.emit (events.js:198:15)
at PassThrough.output.on.error (C:\development\ElectronTut\ytmp3\node_modules\youtube-audio-stream\index.js:38:16)
at PassThrough.emit (events.js:198:15)
at PassThrough.output.on.error (C:\development\ElectronTut\ytmp3\node_modules\youtube-audio-stream\index.js:38:16)
at PassThrough.emit (events.js:198:15)
经过几个小时的研究,我终于放弃了,来到了这里。据我了解,当调用堆栈在下一个进程开始之前没有正确清空时会触发此错误,大多数 Whosebug 论坛一直在讨论异步编程如何导致潜在的无限循环,但我没有搞砸几乎没有足够的地方来理解流中可能发生这种循环的地方。
这是我的服务器代码:
const express = require("express");
const app = new express();
const stream = require('youtube-audio-stream');
const uri = "https://www.youtube.com/watch?v=t1TcDHrkQYg";
app.get("/audio", (req, res) => {
stream(uri).pipe(res);
})
app.listen(3000, () => console.log("Ready!"))
我的前端代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Doc</title>
</head>
<body>
<audio autoplay controls>
<source src="http://localhost:3000/audio" type="audio/mpeg">
</audio>
</body>
</html>
如果这听起来很愚蠢或者我做了一些愚蠢的事情,我深表歉意,但我真的处于边缘并且失去了所有希望。我将如何解决或处理这个范围错误? 如果您愿意,请问任何做过与我正在做的事情类似的人,还有更好的选择吗?
非常感谢您的时间和精力。
已修复,糟糕的库使用的是 ytdl-core 的过时版本!我下载了youtube-audio-stream的源码,然后把ytdl-core更新到最新版本,现在一切正常了!
这是一个没有 server-side 的解决方案。
我(也)花了几个小时试图让这个工作...
在看到您的 post 后,我调查了 youtube-audio-stream
,但我一直没有成功。相反,我最终得到了这个似乎运行良好的解决方案。阅读 this post 后,我修改了一些值以适应 YouTube 当前 (2020) API。
这是一个应该有效的解决方案,适合任何正在寻找的人! Try on CodePen
// YouTube video ID
var videoID = "CMNry4PE93Y";
// Fetch video info (using a proxy if avoid CORS errors)
fetch('https://cors-anywhere.herokuapp.com/' + "https://www.youtube.com/get_video_info?video_id=" + videoID).then(response => {
if (response.ok) {
response.text().then(ytData => {
// parse response to find audio info
var ytData = parse_str(ytData);
var getAdaptiveFormats = JSON.parse(ytData.player_response).streamingData.adaptiveFormats;
var findAudioInfo = getAdaptiveFormats.findIndex(obj => obj.audioQuality);
// get the URL for the audio file
var audioURL = getAdaptiveFormats[findAudioInfo].url;
// update the <audio> element src
var youtubeAudio = document.getElementById('youtube');
youtubeAudio.src = audioURL;
});
}
});
function parse_str(str) {
return str.split('&').reduce(function(params, param) {
var paramSplit = param.split('=').map(function(value) {
return decodeURIComponent(value.replace('+', ' '));
});
params[paramSplit[0]] = paramSplit[1];
return params;
}, {});
}
<audio id="youtube" controls></audio>