server icon indicating copy to clipboard operation
server copied to clipboard

[自己已临时解决]youtube音源无法使用

Open JarmoHu opened this issue 1 year ago • 16 comments

Bug 描述

YouTube音源没有收到信息

预期行为

No response

实际行为

No response

复现步骤

No response

启动命令及环境变量

$env:SELECT_MAX_BR="true"
$env:HTTPS_PROXY="http://127.0.0.1:10811"
$env:HTTP_PROXY="http://127.0.0.1:10811"
$env:all_proxy="socks5://127.0.0.1:10810"
$env:LOG_LEVEL="debug"
node .\app.js -p 52000:52001 -o ytdlp

日志内容

INFO: (app) HTTP Server running @ http://0.0.0.0:52000
INFO: (app) HTTPS Server running @ http://0.0.0.0:52001
DEBUG: (server) TUNNEL
    url: "localhost:52001"
DEBUG: (server) TUNNEL
    url: "p3.music.126.net:443"
DEBUG: (server) TUNNEL
    url: "p4.music.126.net:443"
DEBUG: (server) TUNNEL
    url: "p3.music.126.net:443"
DEBUG: (server) TUNNEL
    url: "p3.music.126.net:443"
DEBUG: (server) TUNNEL
    url: "p3.music.126.net:443"
DEBUG: (server) TUNNEL
    url: "clientlog.music.163.com:443"
DEBUG: (server) TUNNEL
    url: "localhost:52001"
DEBUG: (cache) Cleaning up the expired caches...
    cacheStorageId: "provider/find"
DEBUG: (cache) 1297494226 did not hit. Storing the execution result...
    logKey: 1297494226
    cacheStorageId: "provider/find"
DEBUG: (request) Start requesting https://music.163.com/api/song/detail?ids=[1297494226]
DEBUG: (provider/match) Getting the audio...
    source: "ytdlp"
    info: {
      "name": "Surprise",
      "id": 1297494226,
      "alias": [],
      "duration": 288600,
      "album": {
        "name": "ANGEL TOUCH",
        "id": 72054672
      },
      "artists": [
        {
          "name": "CINDY",
          "id": 28359237
        }
      ],
      "keyword": "Surprise - CINDY"
    }
DEBUG: (cache) Cleaning up the expired caches...
    cacheStorageId: "yt-dlp"
DEBUG: (cache) Something did not hit. Storing the execution result...
    logKey: "Something"
    cacheStorageId: "yt-dlp"
INFO: (spawn) running yt-dlp -f 140 --dump-json ytsearch1:Surprise - CINDY
DEBUG: (spawn) process yt-dlp exited successfully
INFO: (spawn) running yt-dlp -f 140 --dump-json https://www.youtube.com/watch?v=q35Q53G71iE
DEBUG: (spawn) process yt-dlp exited successfully
DEBUG: (request) Start requesting https://rr5---sn-o097znze.googlevideo.com/videoplayback?expire=1707258119&ei=plzCZZ-FPJLBsfIP8NmIgAc&ip=2a09%3Abac5%3A6447%3A1232%3A%3A1d0%3A3f&id=o-AIFhRvS7K44wA2IbkX3w1-nmAF1N1-JFtn2ArbzE9pxl&itag=140&source=youtube&requiressl=yes&xpc=EgVo2aDSNQ%3D%3D&mh=Z4&mm=31%2C26&mn=sn-o097znze%2Csn-2imern76&ms=au%2Conr&mv=m&mvi=5&pl=42&initcwndbps=2038750&vprv=1&svpuc=1&mime=audio%2Fmp4&gir=yes&clen=3167900&dur=195.674&lmt=1695808774149131&mt=1707236236&fvip=3&keepalive=yes&fexp=24007246&c=IOS&txp=4532434&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cxpc%2Cvprv%2Csvpuc%2Cmime%2Cgir%2Cclen%2Cdur%2Clmt&sig=AJfQdSswRQIhANC0ggbPZbiuKqj9I8v8W7Rez708ZOMcTMEHHTaGiCGzAiBrgGAZTk0gq5NorhrQjSZoCq89mZwyZcRxlxYHlR2B2w%3D%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&lsig=AAO5W4owRQIgIia5iuX-OoSNo0DipVkA1cOLxRbVeU8QZOav0xcaaVwCIQDgoYEQ-D8ExgCUlhlRfHfuHA2OZhP-YsHcVoYIoSVZtA%3D%3D
DEBUG: (server) TUNNEL
    url: "localhost:52001"
WARN: (request) The request timed out, or the requester didn't handle the response.
    url: "https://rr5---sn-o097znze.googlevideo.com/videoplayback?expire=1707258119&ei=plzCZZ-FPJLBsfIP8NmIgAc&ip=2a09%3Abac5%3A6447%3A1232%3A%3A1d0%3A3f&id=o-AIFhRvS7K44wA2IbkX3w1-nmAF1N1-JFtn2ArbzE9pxl&itag=140&source=youtube&requiressl=yes&xpc=EgVo2aDSNQ%3D%3D&mh=Z4&mm=31%2C26&mn=sn-o097znze%2Csn-2imern76&ms=au%2Conr&mv=m&mvi=5&pl=42&initcwndbps=2038750&vprv=1&svpuc=1&mime=audio%2Fmp4&gir=yes&clen=3167900&dur=195.674&lmt=1695808774149131&mt=1707236236&fvip=3&keepalive=yes&fexp=24007246&c=IOS&txp=4532434&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cxpc%2Cvprv%2Csvpuc%2Cmime%2Cgir%2Cclen%2Cdur%2Clmt&sig=AJfQdSswRQIhANC0ggbPZbiuKqj9I8v8W7Rez708ZOMcTMEHHTaGiCGzAiBrgGAZTk0gq5NorhrQjSZoCq89mZwyZcRxlxYHlR2B2w%3D%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&lsig=AAO5W4owRQIgIia5iuX-OoSNo0DipVkA1cOLxRbVeU8QZOav0xcaaVwCIQDgoYEQ-D8ExgCUlhlRfHfuHA2OZhP-YsHcVoYIoSVZtA%3D%3D"
DEBUG (RequestCancelled): (provider/match) This request URL has been cancelled: https://rr5---sn-o097znze.googlevideo.com/videoplayback?expire=1707258119&ei=plzCZZ-FPJLBsfIP8NmIgAc&ip=2a09%3Abac5%3A6447%3A1232%3A%3A1d0%3A3f&id=o-AIFhRvS7K44wA2IbkX3w1-nmAF1N1-JFtn2ArbzE9pxl&itag=140&source=youtube&requiressl=yes&xpc=EgVo2aDSNQ%3D%3D&mh=Z4&mm=31%2C26&mn=sn-o097znze%2Csn-2imern76&ms=au%2Conr&mv=m&mvi=5&pl=42&initcwndbps=2038750&vprv=1&svpuc=1&mime=audio%2Fmp4&gir=yes&clen=3167900&dur=195.674&lmt=1695808774149131&mt=1707236236&fvip=3&keepalive=yes&fexp=24007246&c=IOS&txp=4532434&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cxpc%2Cvprv%2Csvpuc%2Cmime%2Cgir%2Cclen%2Cdur%2Clmt&sig=AJfQdSswRQIhANC0ggbPZbiuKqj9I8v8W7Rez708ZOMcTMEHHTaGiCGzAiBrgGAZTk0gq5NorhrQjSZoCq89mZwyZcRxlxYHlR2B2w%3D%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&lsig=AAO5W4owRQIgIia5iuX-OoSNo0DipVkA1cOLxRbVeU8QZOav0xcaaVwCIQDgoYEQ-D8ExgCUlhlRfHfuHA2OZhP-YsHcVoYIoSVZtA%3D%3D
    RequestCancelled: This request URL has been cancelled: https://rr5---sn-o097znze.googlevideo.com/videoplayback?expire=1707258119&ei=plzCZZ-FPJLBsfIP8NmIgAc&ip=2a09%3Abac5%3A6447%3A1232%3A%3A1d0%3A3f&id=o-AIFhRvS7K44wA2IbkX3w1-nmAF1N1-JFtn2ArbzE9pxl&itag=140&source=youtube&requiressl=yes&xpc=EgVo2aDSNQ%3D%3D&mh=Z4&mm=31%2C26&mn=sn-o097znze%2Csn-2imern76&ms=au%2Conr&mv=m&mvi=5&pl=42&initcwndbps=2038750&vprv=1&svpuc=1&mime=audio%2Fmp4&gir=yes&clen=3167900&dur=195.674&lmt=1695808774149131&mt=1707236236&fvip=3&keepalive=yes&fexp=24007246&c=IOS&txp=4532434&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cxpc%2Cvprv%2Csvpuc%2Cmime%2Cgir%2Cclen%2Cdur%2Clmt&sig=AJfQdSswRQIhANC0ggbPZbiuKqj9I8v8W7Rez708ZOMcTMEHHTaGiCGzAiBrgGAZTk0gq5NorhrQjSZoCq89mZwyZcRxlxYHlR2B2w%3D%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&lsig=AAO5W4owRQIgIia5iuX-OoSNo0DipVkA1cOLxRbVeU8QZOav0xcaaVwCIQDgoYEQ-D8ExgCUlhlRfHfuHA2OZhP-YsHcVoYIoSVZtA%3D%3D
        at m (E:\Softwares\Netease-server-enhanced\precompiled\app.js:3:40795)
        at ClientRequest.<anonymous> (E:\Softwares\Netease-server-enhanced\precompiled\app.js:3:40997)
        at Object.onceWrapper (node:events:631:28)
        at ClientRequest.emit (node:events:517:28)
        at TLSSocket.emitRequestTimeout (node:_http_client:847:9)
        at Object.onceWrapper (node:events:631:28)
        at TLSSocket.emit (node:events:529:35)
        at Socket._onTimeout (node:net:598:8)
        at listOnTimeout (node:internal/timers:569:17)
        at process.processTimers (node:internal/timers:512:7)
ERROR (SongNotAvailable): (hook) This song "?" is not available in any source
    SongNotAvailable: This song "?" is not available in any source
        at b (E:\Softwares\Netease-server-enhanced\precompiled\app.js:3:29879)
        at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
        at async Promise.all (index 0)
DEBUG: (cache) Cleaning up the expired caches...
    cacheStorageId: "provider/find"
DEBUG: (cache) 22794457 did not hit. Storing the execution result...
    logKey: 22794457
    cacheStorageId: "provider/find"
DEBUG: (request) Start requesting https://music.163.com/api/song/detail?ids=[22794457]
DEBUG: (provider/match) Getting the audio...
    source: "ytdlp"
    info: {
      "name": "骞搞仜銇倐銇仌銇?,
      "id": 22794457,
      "alias": [],
      "duration": 327146,
      "album": {
        "name": "Expressions",
        "id": 2094911
      },
      "artists": [
        {
          "name": "绔瑰唴銇俱倞銈?,
          "id": 17916
        }
      ],
      "keyword": "骞搞仜銇倐銇仌銇?- 绔瑰唴銇俱倞銈?
    }
DEBUG: (cache) Cleaning up the expired caches...
    cacheStorageId: "yt-dlp"
DEBUG: (cache) Something did not hit. Storing the execution result...
    logKey: "Something"
    cacheStorageId: "yt-dlp"
INFO: (spawn) running yt-dlp -f 140 --dump-json ytsearch1:骞搞仜銇倐銇仌銇?- 绔瑰唴銇俱倞銈?[39m
DEBUG: (spawn) process yt-dlp exited successfully
INFO: (spawn) running yt-dlp -f 140 --dump-json https://www.youtube.com/watch?v=TLE6JYUiCbI
DEBUG: (spawn) process yt-dlp exited successfully
DEBUG: (request) Start requesting https://rr4---sn-o097znze.googlevideo.com/videoplayback?expire=1707258148&ei=xFzCZb-JN_PGsfIPg9aTqAQ&ip=2a09%3Abac5%3A6447%3A1232%3A%3A1d0%3A3f&id=o-AKuz2fSGX2-bHLJdBz1ilZTTk_jiJty3HqnPC7xCX5sf&itag=140&source=youtube&requiressl=yes&xpc=EgVo2aDSNQ%3D%3D&mh=Ow&mm=31%2C26&mn=sn-o097znze%2Csn-2imern76&ms=au%2Conr&mv=m&mvi=4&pl=42&initcwndbps=2038750&vprv=1&svpuc=1&mime=audio%2Fmp4&gir=yes&clen=2114406&dur=130.589&lmt=1691753982111767&mt=1707236236&fvip=3&keepalive=yes&fexp=24007246&c=IOS&txp=6218224&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cxpc%2Cvprv%2Csvpuc%2Cmime%2Cgir%2Cclen%2Cdur%2Clmt&sig=AJfQdSswRgIhAJsCg19_EY2oBs4gDybySBrfwGw9PHxhczPI9zq4CwaxAiEAxq_8KHGNnLdQH0yCpXjC7c9YgDXp63ROMVcZqvhUj4M%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&lsig=AAO5W4owRQIgZ39x2_Ms85VEZEoa4zJaWrYykSJcCoRm4LGf9xLyRwECIQDKmuHjcEEFJc5A8gjTxkYcZcCiNYIa-SsY3MZ0fTgLlQ%3D%3D
WARN: (request) The request timed out, or the requester didn't handle the response.
    url: "https://rr4---sn-o097znze.googlevideo.com/videoplayback?expire=1707258148&ei=xFzCZb-JN_PGsfIPg9aTqAQ&ip=2a09%3Abac5%3A6447%3A1232%3A%3A1d0%3A3f&id=o-AKuz2fSGX2-bHLJdBz1ilZTTk_jiJty3HqnPC7xCX5sf&itag=140&source=youtube&requiressl=yes&xpc=EgVo2aDSNQ%3D%3D&mh=Ow&mm=31%2C26&mn=sn-o097znze%2Csn-2imern76&ms=au%2Conr&mv=m&mvi=4&pl=42&initcwndbps=2038750&vprv=1&svpuc=1&mime=audio%2Fmp4&gir=yes&clen=2114406&dur=130.589&lmt=1691753982111767&mt=1707236236&fvip=3&keepalive=yes&fexp=24007246&c=IOS&txp=6218224&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cxpc%2Cvprv%2Csvpuc%2Cmime%2Cgir%2Cclen%2Cdur%2Clmt&sig=AJfQdSswRgIhAJsCg19_EY2oBs4gDybySBrfwGw9PHxhczPI9zq4CwaxAiEAxq_8KHGNnLdQH0yCpXjC7c9YgDXp63ROMVcZqvhUj4M%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&lsig=AAO5W4owRQIgZ39x2_Ms85VEZEoa4zJaWrYykSJcCoRm4LGf9xLyRwECIQDKmuHjcEEFJc5A8gjTxkYcZcCiNYIa-SsY3MZ0fTgLlQ%3D%3D"
DEBUG (RequestCancelled): (provider/match) This request URL has been cancelled: https://rr4---sn-o097znze.googlevideo.com/videoplayback?expire=1707258148&ei=xFzCZb-JN_PGsfIPg9aTqAQ&ip=2a09%3Abac5%3A6447%3A1232%3A%3A1d0%3A3f&id=o-AKuz2fSGX2-bHLJdBz1ilZTTk_jiJty3HqnPC7xCX5sf&itag=140&source=youtube&requiressl=yes&xpc=EgVo2aDSNQ%3D%3D&mh=Ow&mm=31%2C26&mn=sn-o097znze%2Csn-2imern76&ms=au%2Conr&mv=m&mvi=4&pl=42&initcwndbps=2038750&vprv=1&svpuc=1&mime=audio%2Fmp4&gir=yes&clen=2114406&dur=130.589&lmt=1691753982111767&mt=1707236236&fvip=3&keepalive=yes&fexp=24007246&c=IOS&txp=6218224&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cxpc%2Cvprv%2Csvpuc%2Cmime%2Cgir%2Cclen%2Cdur%2Clmt&sig=AJfQdSswRgIhAJsCg19_EY2oBs4gDybySBrfwGw9PHxhczPI9zq4CwaxAiEAxq_8KHGNnLdQH0yCpXjC7c9YgDXp63ROMVcZqvhUj4M%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&lsig=AAO5W4owRQIgZ39x2_Ms85VEZEoa4zJaWrYykSJcCoRm4LGf9xLyRwECIQDKmuHjcEEFJc5A8gjTxkYcZcCiNYIa-SsY3MZ0fTgLlQ%3D%3D
    RequestCancelled: This request URL has been cancelled: https://rr4---sn-o097znze.googlevideo.com/videoplayback?expire=1707258148&ei=xFzCZb-JN_PGsfIPg9aTqAQ&ip=2a09%3Abac5%3A6447%3A1232%3A%3A1d0%3A3f&id=o-AKuz2fSGX2-bHLJdBz1ilZTTk_jiJty3HqnPC7xCX5sf&itag=140&source=youtube&requiressl=yes&xpc=EgVo2aDSNQ%3D%3D&mh=Ow&mm=31%2C26&mn=sn-o097znze%2Csn-2imern76&ms=au%2Conr&mv=m&mvi=4&pl=42&initcwndbps=2038750&vprv=1&svpuc=1&mime=audio%2Fmp4&gir=yes&clen=2114406&dur=130.589&lmt=1691753982111767&mt=1707236236&fvip=3&keepalive=yes&fexp=24007246&c=IOS&txp=6218224&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cxpc%2Cvprv%2Csvpuc%2Cmime%2Cgir%2Cclen%2Cdur%2Clmt&sig=AJfQdSswRgIhAJsCg19_EY2oBs4gDybySBrfwGw9PHxhczPI9zq4CwaxAiEAxq_8KHGNnLdQH0yCpXjC7c9YgDXp63ROMVcZqvhUj4M%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&lsig=AAO5W4owRQIgZ39x2_Ms85VEZEoa4zJaWrYykSJcCoRm4LGf9xLyRwECIQDKmuHjcEEFJc5A8gjTxkYcZcCiNYIa-SsY3MZ0fTgLlQ%3D%3D
        at m (E:\Softwares\Netease-server-enhanced\precompiled\app.js:3:40795)
        at ClientRequest.<anonymous> (E:\Softwares\Netease-server-enhanced\precompiled\app.js:3:40997)
        at Object.onceWrapper (node:events:631:28)
        at ClientRequest.emit (node:events:517:28)
        at TLSSocket.emitRequestTimeout (node:_http_client:847:9)
        at Object.onceWrapper (node:events:631:28)
        at TLSSocket.emit (node:events:529:35)
        at Socket._onTimeout (node:net:598:8)
        at listOnTimeout (node:internal/timers:569:17)
        at process.processTimers (node:internal/timers:512:7)
ERROR (SongNotAvailable): (hook) This song "?" is not available in any source
    SongNotAvailable: This song "?" is not available in any source
        at b (E:\Softwares\Netease-server-enhanced\precompiled\app.js:3:29879)
        at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
        at async Promise.all (index 0)
DEBUG: (server) TUNNEL
    url: "localhost:52001"
DEBUG: (server) TUNNEL
    url: "localhost:52001"
DEBUG: (server) TUNNEL
    url: "localhost:52001"
DEBUG: (hook) unblockLyricsEffects() has been triggered.
DEBUG: (hook) unblockLyricsEffects() has been triggered.
DEBUG: (hook) unblockLyricsEffects() has been triggered.

网易云音乐歌曲链接

No response

网易云音乐版本号

3.0.0

操作系统

win10 x64

其他信息

No response

问题排查

  • [X] 我确认我使用的核心是由 UnblockNeteaseMusic 项目官方发行,不是其他任何 fork。
  • [X] 我确认我已经升级到了最新的核心版本(推荐使用最新构建而不是 release)。
  • [X] 我确认我已经启用了 HTTPS 端口。
  • [X] 我确认我已经正确设置了 EndPoint。
  • [X] 我确认我已经在对应的客户端正确安装了 CA 证书。

JarmoHu avatar Feb 06 '24 16:02 JarmoHu

我自己临时解决了,主要是request.js需要添加代理,暂时不支持和自定义上游(就是参数里的-u)共存。 代码如下: 修改src/request.js,记得修改代码中的代理服务器的地址和端口。

const zlib = require('zlib');
const http = require('http');
const https = require('https');
const ON_CANCEL = require('./cancel');
const RequestCancelled = require('./exceptions/RequestCancelled');
const { logScope } = require('./logger');
const parse = require('url').parse;
const format = require('url').format;

const logger = logScope('request');
const timeoutThreshold = 10 * 1000;

//process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0';
const HttpsProxyAgent = require('https-proxy-agent').HttpsProxyAgent;
// 代理服务器的地址和端口
const proxyHost = '127.0.0.1';
const proxyPort = 10809;

const translate = (host) => (global.hosts || {})[host] || host;
const create = (url, proxy) =>
	(((typeof proxy === 'undefined' ? global.proxy : proxy) || url).protocol ===
	'https:'
		? https
		: http
	).request;

const configure = (method, url, headers, proxy) => {
	headers = headers || {};
	proxy = typeof proxy === 'undefined' ? global.proxy : proxy;
	if ('content-length' in headers) delete headers['content-length'];

	const options = {};
	options._headers = headers;
	if (proxy && url.protocol === 'https:') {
		options.method = 'CONNECT';
		options.headers = Object.keys(headers).reduce(
			(result, key) =>
				Object.assign(
					result,
					['host', 'user-agent'].includes(key) && {
						[key]: headers[key],
					}
				),
			{}
		);
	} else {
		options.method = method;
		options.headers = headers;
	}

	if (proxy) {
		options.hostname = translate(proxy.hostname);
		options.port = proxy.port || (proxy.protocol === 'https:' ? 443 : 80);
		options.path =
			url.protocol === 'https:'
				? translate(url.hostname) + ':' + (url.port || 443)
				: 'http://' + translate(url.hostname) + url.path;
	} else {
		options.hostname = translate(url.hostname);
		options.port = url.port || (url.protocol === 'https:' ? 443 : 80);
		options.path = url.path;
	}

	if (
		(url.hostname.endsWith('googlevideo.com') ||
			url.hostname.endsWith('youtube.com')) &&
		url.protocol === 'https:'
	) {
		options.agent = new HttpsProxyAgent({
			host: proxyHost,
			port: proxyPort,
		});
	}
	return options;
};

/**
 * @typedef {((raw: true) => Promise<Buffer>) | ((raw: false) => Promise<string>)} RequestExtensionBody
 */

/**
 * @template T
 * @typedef {{url: string, body: RequestExtensionBody, json: () => Promise<T>, jsonp: () => Promise<T>}} RequestExtension
 */

/**
 * @template T
 * @param {string} method
 * @param {string} receivedUrl
 * @param {Object?} receivedHeaders
 * @param {unknown?} body
 * @param {unknown?} proxy
 * @param {CancelRequest?} cancelRequest
 * @return {Promise<http.IncomingMessage & RequestExtension<T>>}
 */
const request = (
	method,
	receivedUrl,
	receivedHeaders,
	body,
	proxy,
	cancelRequest
) => {
	const url = parse(receivedUrl);
	/* @type {Partial<Record<string,string>>} */
	const headers = receivedHeaders || {};
	const options = configure(
		method,
		url,
		{
			host: url.hostname,
			accept: 'application/json, text/plain, */*',
			'accept-encoding': 'gzip, deflate',
			'accept-language': 'zh-CN,zh;q=0.9',
			'user-agent':
				'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36',
			...headers,
		},
		proxy
	);

	return new Promise((resolve, reject) => {
		logger.debug(`Start requesting ${receivedUrl}`);

		const clientRequest = create(url, proxy)(options);
		const destroyClientRequest = function () {
			// We destroy the request and throw RequestCancelled
			// when the request has been cancelled.
			clientRequest.destroy(new RequestCancelled(format(url)));
		};

		cancelRequest?.on(ON_CANCEL, destroyClientRequest);
		if (cancelRequest?.cancelled ?? false) destroyClientRequest();

		clientRequest
			.setTimeout(timeoutThreshold, () => {
				logger.warn(
					{
						url: format(url),
					},
					`The request timed out, or the requester didn't handle the response.`
				);
				destroyClientRequest();
			})
			.on('response', (response) => resolve(response))
			.on('connect', (_, socket) => {
				logger.debug(
					'received CONNECT, continuing with https.request()...'
				);
				https
					.request({
						method: method,
						path: url.path,
						headers: options._headers,
						socket: socket,
						agent: false,
					})
					.on('response', (response) => resolve(response))
					.on('error', (error) => reject(error))
					.end(body);
			})
			.on('error', (error) => reject(error))
			.end(options.method.toUpperCase() === 'CONNECT' ? undefined : body);
	}).then(
		/** @param {http.IncomingMessage} response */
		(response) => {
			if (cancelRequest?.cancelled ?? false)
				return Promise.reject(new RequestCancelled(format(url)));

			if ([201, 301, 302, 303, 307, 308].includes(response.statusCode)) {
				const redirectTo = url.resolve(
					response.headers.location || url.href
				);

				logger.debug(`Redirect to ${redirectTo}`);
				delete headers.host;
				return request(method, redirectTo, headers, body, proxy);
			}

			return Object.assign(response, {
				url,
				body: (raw) => read(response, raw),
				json: () => json(response),
				jsonp: () => jsonp(response),
			});
		}
	);
};

const read = (connect, raw) =>
	new Promise((resolve, reject) => {
		const chunks = [];
		connect
			.on('data', (chunk) => chunks.push(chunk))
			.on('end', () => resolve(Buffer.concat(chunks)))
			.on('error', (error) => reject(error));
	}).then((buffer) => {
		if (buffer.length) {
			switch (connect.headers['content-encoding']) {
				case 'deflate':
				case 'gzip':
					buffer = zlib.unzipSync(buffer);
					break;
				case 'br':
					buffer = zlib.brotliDecompressSync(buffer);
					break;
			}
		}
		return raw ? buffer : buffer.toString();
	});

const json = (connect) => read(connect, false).then((body) => JSON.parse(body));
const jsonp = (connect) =>
	read(connect, false).then((body) =>
		JSON.parse(body.slice(body.indexOf('(') + 1, -')'.length))
	);

request.read = read;
request.create = create;
request.translate = translate;
request.configure = configure;

module.exports = request;

需要在程序所在文件夹里安装https-proxy-agent

npm install https-proxy-agent

JarmoHu avatar Feb 13 '24 16:02 JarmoHu

大佬 youtube的音源怎么添加 有没有教程 我看不懂github 我现在有些歌曲没办法播放 也解灰了 音源也添加了 但是youtube的音源不知道是啥 微信截图_20240309005327

laonuodr avatar Mar 08 '24 16:03 laonuodr

你这个是啥?我是自己魔改的nodejs代码?

JarmoHu avatar Mar 09 '24 03:03 JarmoHu

问一下,我已经安装了ytdlp,为什么还是提示

You must install "yt-dlp" before using the "ytdlp" source.

wosuxiongmao avatar Mar 12 '24 03:03 wosuxiongmao

问一下,我已经安装了ytdlp,为什么还是提示

You must install "yt-dlp" before using the "ytdlp" source.

我是把exe和yt-dlp放一个目录就能用了

jukk8866 avatar Mar 20 '24 07:03 jukk8866

问一下,我已经安装了ytdlp,为什么还是提示 You must install "yt-dlp" before using the "ytdlp" source.

我是把exe和yt-dlp放一个目录就能用了

是的,要么放一起,要么把yt-dlp所在文件夹添加到系统环境变量的path中

JarmoHu avatar Mar 20 '24 08:03 JarmoHu

感谢,不过我这边换成了socks: const SocksProxyAgent = require('socks-proxy-agent').SocksProxyAgent;

不知道哪里有问题,还是不能下载: INFO: (spawn) running yt-dlp -f 140 --dump-json ytsearch1:My love come true from your heart - LONG SHOT PARTY Pointirhythm WARN: (spawn) [yt-dlp][stderr] WARNING: [youtube:search] Unable to download webpage: (<urllib3.connection.HTTPSConnection object at 0x000001E1284FA100>, 'Connection to www.youtube.com timed out. (connect timeout=20.0)')

看了一下src/provider/yt-dlp文件,id没有获取成功,好像完全没连上youtube,可为什么命令行里能获取啊?

Hipponensis avatar Mar 20 '24 11:03 Hipponensis

感谢,不过我这边换成了socks: const SocksProxyAgent = require('socks-proxy-agent').SocksProxyAgent;

不知道哪里有问题,还是不能下载: INFO: (spawn) running yt-dlp -f 140 --dump-json ytsearch1:My love come true from your heart - LONG SHOT PARTY Pointirhythm WARN: (spawn) [yt-dlp][stderr] WARNING: [youtube:search] Unable to download webpage: (<urllib3.connection.HTTPSConnection object at 0x000001E1284FA100>, 'Connection to www.youtube.com timed out. (connect timeout=20.0)')

看了一下src/provider/yt-dlp文件,id没有获取成功,好像完全没连上youtube,可为什么命令行里能获取啊?

我那个文件修改了好多地方,你再看看?

JarmoHu avatar Mar 20 '24 14:03 JarmoHu

请问一下ubnuntu20.04如何操作

unutjpwpd avatar May 03 '24 08:05 unutjpwpd

参考issues 问题1 问题2

本来我也想用楼主的方法但我用着的代理没有http代理选项,然后参考了楼上用sock方法的这位

我更新一下这个问题吧。对于需要科学上网环境情况下(以下以yt-dlp为示例): 1、改动src/provider/yt-dlp文件,这里添加--proxy','socks5://127.0.0.1:10808(注意格式)

const dlArguments = (query) => ['-f', '140', '--dump-json', query];
改为
const dlArguments = (query) => ['--proxy','socks5://127.0.0.1:10808','-f', '140', '--dump-json', query];

这里添加代理只能为yt-dlp程序提供代理环境,我们还需要对UnblockNeteaseMusic项目进行添加请求的代理

2、改动src/request.js文件,http的方法请参考楼主,我是参考楼上这位用的socks的方法,但似乎差点参数,然后我去找了下资料,贴下关键code

//process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0';
//
// const HttpsProxyAgent = require('https-proxy-agent').HttpsProxyAgent;
const SocksProxyAgent = require('socks-proxy-agent').SocksProxyAgent;
// // 代理服务器的地址和端口
const proxyHost = '127.0.0.1';
const proxyPort = 10808;
//socks5|http
const proxyType = 'socks5';

const translate = (host) => (global.hosts || {})[host] || host;
const create = (url, proxy) =>
	(((typeof proxy === 'undefined' ? global.proxy : proxy) || url).protocol ===
	'https:'
		? https
		: http
	).request;

const configure = (method, url, headers, proxy) => {
	headers = headers || {};
	proxy = typeof proxy === 'undefined' ? global.proxy : proxy;
	if ('content-length' in headers) delete headers['content-length'];

	const options = {};
	options._headers = headers;
	if (proxy && url.protocol === 'https:') {
		options.method = 'CONNECT';
		options.headers = Object.keys(headers).reduce(
			(result, key) =>
				Object.assign(
					result,
					['host', 'user-agent'].includes(key) && {
						[key]: headers[key],
					}
				),
			{}
		);
	} else {
		options.method = method;
		options.headers = headers;
	}

	if (proxy) {
		options.hostname = translate(proxy.hostname);
		options.port = proxy.port || (proxy.protocol === 'https:' ? 443 : 80);
		options.path =
			url.protocol === 'https:'
				? translate(url.hostname) + ':' + (url.port || 443)
				: 'http://' + translate(url.hostname) + url.path;
	} else {
		options.hostname = translate(url.hostname);
		options.port = url.port || (url.protocol === 'https:' ? 443 : 80);
		options.path = url.path;
	}
	// //begin other 
	if (
		(url.hostname.endsWith('googlevideo.com') ||
			url.hostname.endsWith('youtube.com')) &&
		url.protocol === 'https:'
	) {
                //这里.....
		//options.agent = new SocksProxyAgent('socks5://127.0.0.1:10808');
               //options.agent = new HttpsProxyAgent({});
		options.agent = new SocksProxyAgent({
                //http下可能需要注释掉protocol
		protocol: `${proxyType}:`,
        	hostname: proxyHost,
        	port: proxyPort
		});

	}
	return options;
};

LeonGinger avatar May 14 '24 05:05 LeonGinger

很感謝你們幫忙 patch YouTube 音源的問題~

不知道有沒有興趣發個 Pull Request 到上游,方便合併,讓更多人受益~ 😄

pan93412 avatar May 19 '24 09:05 pan93412

很感謝你們幫忙 patch YouTube 音源的問題~

不知道有沒有興趣發個 Pull Request 到上游,方便合併,讓更多人受益~ 😄

其实我就是一直有一个问题要问,启动参数中的-u添加上游代理指的是什么?和我通过本地http代理有什么区别?

JarmoHu avatar May 21 '24 06:05 JarmoHu

手上只有黑裙6.0,只能node 12套件,只能去改precompiled/app.js, 成功了,然后挂载到docker也成功了

gavinliuisme avatar Jun 04 '24 13:06 gavinliuisme

获取到音频后,你们能正常完整播放吗?我现在开着代理还是只能播放 9s

deckvig avatar Jun 09 '24 06:06 deckvig

获取到音频后,你们能正常完整播放吗?我现在开着代理还是只能播放 9s

我也是只有9s,但是看后台获取到的直链是完整的全部歌曲 image

uxfion avatar Jun 15 '24 02:06 uxfion

其实我就是一直有一个问题要问,启动参数中的-u添加上游代理指的是什么?和我通过本地http代理有什么区别?

-u 应该是指定用于和网易云音乐服务器通讯的代理,继承自 nondanee 的代码,历史问题了。

1715173329 avatar Jul 17 '24 04:07 1715173329