解析网页版的播放接口原理，基于实战完整实现搜索、多音质获取、流式代理播放、歌词同步等细节。一、碎播放接口未对外开放，却可以通过开发者工具抓取分析。记录一下网页版播放链路的逆向分析过程，以及 从零实现一个完整播放器 的全流程，包含：歌曲搜索（支持分页）多音质播放链接获取（FLAC / 320kbps / 128kbps / AAC）流式服务端代理绕过防盗链歌词实时获取与高亮同步自定义播放器 UI免责声明： 本文仅用于技术研究学习，请尊重音乐版权，所得数据仅限个人测试使用。二、起点：浏览器开发者工具网络请求打开 https://y.qq.com/，搜索任意歌曲，按 F12 → Network 面板。点击播放后，主要关注三类请求：请求类型接口地址用途搜索c.y.qq.com/soso/fcgi-bin/search_for_qq_cp获取歌曲元数据播放凭证u.y.qq.com/cgi-bin/musicu.fcg POST获取 vkey 和 CDN 地址音频文件isure.stream.qqmusic.qq.com/*实际音频流搜索接口GET https://c.y.qq.com/soso/fcgi-bin/search_for_qq_cp?w=七里香&p=1&n=20&format=json&platform=h5 返回 JSONP 格式数据，关键字段： { "songname": "七里香", "songmid": "004Z8Ihr0JIu5s", "singer": [{"name": "周杰伦"}], "albummid": "003DFRzD192KKD" } songmid 是每首歌的唯一标识，后续所有接口都依赖它。albummid 用于拼接专辑封面 URL。播放凭证（vkey）接口 POST https://u.y.qq.com/cgi-bin/musicu.fcg Content-Type: application/json 请求体：{ "req_0": { "module": "vkey.GetVkeyServer", "method": "CgiGetVkey", "param": { "filename": ["M500004Z8Ihr0JIu5s004Z8Ihr0JIu5s.mp3"], "guid": "a9444620715462ea", "songmid": ["004Z8Ihr0JIu5s"], "songtype": [0], "uin": "0", "loginflag": 1, "platform": "20" } }, "comm": { "uin": 0, "format": "json", "ct": 19, "cv": 0 } } filename 格式规则： {音质前缀}{songmid}{songmid}.{后缀}前缀后缀音质歌曲大小F000.flac无损 FLAC~30MBM800.mp3高品质 320kbps~10MBM500.mp3标准 128kbps~4MBC400.m4aAAC 格式~3MB响应中关键返回结构（两种历史格式需兼容）：格式一（midurlinfo）：{ "midurlinfo": [{"purl": "M500xxx.mp3?vkey=7D54ACE0&guid=xxx&uin=6841847"}], "sip": ["https://isure.stream.qqmusic.qq.com/"] } 最终 URL = sip[0] + midurlinfo[0].purl格式二（testfile2g）： { "testfile2g": "C400xxx.m4a?guid=xxx&vkey=7D54ACE0", "sip": ["http://aqqmusic.tc.qq.com/"] } 最终 URL = sip[0] + testfile2g（注意 HTTP → HTTPS的转换）三、GUID 与 CookieGUID 生成GUID 是 16 位随机十六进制字符串，没有校验逻辑，每次请求可随机生成： $guid = substr(md5(uniqid(mt_rand(), true)), 0, 16); 不同Cookie的作用状态作用音质无 Cookie❌ 被 CDN 拦截无法播放音乐无无会员 Cookie✅ 可试听128kbps无会员 Cookie✅ 完整播放免费歌曲320kbpsVIP Cookie✅ 完整播放FLAC 无损Cookie 中关键字段：uin（QQ号）、qqmusic_key（登录态密钥）。有效期暂未测试过。四、防盗链跟快速代理Referer检查CDN 检查 HTTP Referer 头——只有来自 y.qq.com 的请求才被允许。浏览器 标签无法自定义 Referer，所以需要服务端代理。否则提示：禁止跨域访问转发代理传统代理使用 file_get_contents 下载完整文件后再输出，延迟大（几十秒）。优化方案是使用 fopen + fpassthru 边下载边转发： $fp = @fopen($url, 'rb', false, stream_context_create([ 'http' => ['header' => "User-Agent: Mozilla/5.0\r\nReferer: https://y.qq.com/"] ])); if ($fp) { fpassthru($fp); fclose($fp); } 这样浏览器在收到第一个数据包后就可以开始缓冲播放，延迟从数十秒降到 1-3 秒。4.3 代理流程 ┌─────────┐ src="proxy.php?url=..." ┌──────────┐ fopen+fpassthru ┌──────────────┐ │ Browser │ ←──────────────────────── │ PHP Proxy│ ←─────────────── │ QQ Music CDN │ │ │ 流式音频数据 │ │ 带 Referer 请求 │ │ └─────────┘ └──────────┘ └──────────────┘ 五、完整实现HTTP工具 function http_get($url, $referer = 'https://y.qq.com/') { $ctx = stream_context_create([ 'http' => [ 'method' => 'GET', 'header' => "User-Agent: Mozilla/5.0\r\nReferer: $referer\r\n", 'timeout' => 10 ], 'ssl' => ['verify_peer' => false, 'verify_host' => false] ]); return @file_get_contents($url, false, $ctx); } function http_post($data, $cookie = '') { $json = json_encode($data); $header = "User-Agent: Mozilla/5.0\r\n" . "Referer: https://y.qq.com/\r\n" . "Content-Type: application/json\r\n" . "Content-Length: " . strlen($json); if ($cookie) $header .= "\r\nCookie: " . $cookie; $ctx = stream_context_create([ 'http' => ['method' => 'POST', 'header' => $header, 'content' => $json, 'timeout' => 8], 'ssl' => ['verify_peer' => false, 'verify_host' => false] ]); return @file_get_contents("https://u.y.qq.com/cgi-bin/musicu.fcg", false, $ctx); } 搜索接口实现 $kw = $_GET['w']; $page = $_GET['p'] ?? 1; $resp = http_get("https://c.y.qq.com/soso/fcgi-bin/search_for_qq_cp?" . http_build_query([ 'w' => $kw, 'p' => $page, 'n' => 20, 'format' => 'json', 'platform' => 'h5', 'g_tk' => '5381', 'uin' => '0' ])); if (preg_match('/^[A-Za-z_]+\((.*)\)$/s', $resp, $m)) $resp = $m[1]; $data = json_decode($resp, true); $songs = $data['data']['song']['list'] ?? []; 返回的 albummid 用于拼接封面图 URL：https://y.qq.com/music/photo_new/T002R300x300M000{albummid}.jpg不同音质的获取每个音质独立请求 vkey 接口，按优先级排序：从响应中提取 midurlinfo / testfile2g构造完整播放 URL 并收集到 $urls 数组 $fmtList = [ ['F000', '.flac', '无损FLAC'], ['M800', '.mp3', '高品质320kbps'], ['M500', '.mp3', '标准128kbps'], ['C400', '.m4a', 'AAC'], ]; foreach ($fmtList as $fmt) { $body["req_0"]["param"]["filename"] = [$fmt[0] . $mid . $mid . $fmt[1]]; $resp = http_post($body, $cookie); } 歌词获取 $resp = http_get( "https://c.y.qq.com/lyric/fcgi-bin/fcg_query_lyric_new.fcg?" . "songmid={$mid}&pcachetime=" . round(microtime(true) * 1000) ); $d = json_decode($resp, true); $lyricRaw = base64_decode($d['lyric']); // 解析 LRC 格式 preg_match_all('/\[(\d{2}):(\d{2})\.(\d{2,3})\](.*)/', $lyricRaw, $m, PREG_SET_ORDER); foreach ($m as $v) { $ms = intval($v[3]); if (strlen($v[3]) == 2) $ms *= 10; // 2位毫秒 → 补成3位 $lines[] = [ 't' => intval($v[1])*60 + intval($v[2]) + $ms/1000, 'c' => trim($v[4]) ]; } 音频代理 if ($action == 'proxy') { $url = $_GET['url']; $hdr = "User-Agent: Mozilla/5.0\r\nReferer: https://y.qq.com/"; if ($cookie) $hdr .= "\r\nCookie: " . $cookie; $fp = @fopen($url, 'rb', false, stream_context_create([ 'http' => ['method' => 'GET', 'header' => $hdr, 'timeout' => 60], 'ssl' => ['verify_peer' => false, 'verify_host' => false] ])); if ($fp) { fpassthru($fp); fclose($fp); } exit; } 六、前端实现要点播放器ui扔给AI处理就行了歌词同步前端通过 ontimeupdate 事件（每 250ms）获取播放进度，匹配歌词时间戳： audio.ontimeupdate = function() { var cur = audio.currentTime; for (var i = lyrics.length - 1; i >= 0; i--) { if (lyrics[i].t <= cur + 0.3) { lines[i].style.color = "#007aff"; lines[i].scrollIntoView({block: "center"}); break; } } }; API 返回的播放链接包含 vkey、uin、guid 等敏感信息，展示到调试面板前进行脱敏处理cookies请自己F12网页登录抓取,复制整个cookies值，粘贴到下面文件的头部本文对应完整单文件实现可在配套的 qqmusic-demo.php 查看。该文件集成了搜索、多音质获取、流式代理、歌词同步、自定义播放器等全部功能，可直接部署运行。网盘规则,下载后删除.txt后缀蓝奏云
本地搭建环境，很多人会忽视php加入系统的环境变量本篇内容将会以小皮建站程序作为教材使用。第一步找到php所在位置打开小皮建站，点击左侧的设置，点文件位置，点击PHP双击你要的php版本，进入，然后复制地址栏里的地址，例如我的是D:\phpstudy_pro\Extensions\php\php8.2.9nts右键我的电脑------选择属性-----找到右侧高级系统设置在系统属性窗口----点击环境变量---选择Path(一个在用户变量里面。一个在系统变量里面。二选一即可)--点击编辑在编辑环境变量窗口-----选择添加--把刚刚的php路径复制进去即可完成--最后点击确定最后在终端里输入php -v 看下是否能正常输出php的版本号吧，如果可以就说明已经配置正确了。
1. 安装PHP：PHP是服务端经常使用的编程语言，命令只需一行：sudo apt install php-fpm一旦安装完成，FPM 服务将会自动启动。想要检查服务状态，运行（这里安装的是7.4版本，可以使用命令php -v查看，将7.4改成实际安装版本即可）：sudo systemctl status php7.4-fpm还可以安装mysql扩展，以便使得PHP可以做数据库相关操作：sudo apt install php-mysql安装后也需要重启PHP-FPM服务，以确保新更新被运行：sudo systemctl restart php7.4-fpm2. Nginx的相关配置2.1创建文件：sudo vim /etc/nginx/php-fpm74.conf，写入如下内容：location ~ .*\.php$ { fastcgi_pass 127.0.0.1:9004; fastcgi_param PHP_SELF $uri; fastcgi_param SERVER_NAME $host; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_index index.php; include fastcgi_params; include php_cgi.conf; }fastcgi_pass 127.0.0.1:9004代表要将信息通过9004端口传递给php-fpm处理，2~6行都是定义的变量，7，8行是include的两个文件。2.2创建文件：sudo vim /etc/nginx/php_cgi.conf，写入如下内容：fastcgi_connect_timeout 300s; fastcgi_send_timeout 300s; fastcgi_read_timeout 300s; fastcgi_buffer_size 128k; fastcgi_buffers 8 128k; fastcgi_busy_buffers_size 256k; fastcgi_temp_file_write_size 256k; fastcgi_intercept_errors on;2.3创建文件：sudo vim /etc/nginx/conf.d/www.conf，写入如下内容：server { server_name 114.1.114.1; index index.php; root /opt/www; include php-fpm74.conf; }进入/opt目录，新建www目录，这个目录就是默认网站的页面所在的目录了：cd /opt sudo mkdir www3. php-fpm的相关配置创建文件：sudo vim /etc/php-fpm.d/www.conf，(注意这个地方写的位置需要自己注意一下，我的安装位置是/etc/php/7.4/fpm,里面有这样四个文件或目录：conf.d php-fpm.conf php.ini pool.d，php-fpm.conf即主配置文件，其中有一句这样的语句：include=/etc/php/7.4/fpm/pool.d/*.conf，意思是导入以conf结尾的文件配置，所以我的文件位置在这个地方/etc/php/7.4/fpm/pool.d/www.conf)，写入如下内容：[global] pid = run/php-fpm.pid error_log = log/error.log [www] listen = 127.0.0.1:9004 user = www-data group = www-data pm = static pm.max_children = 5 rlimit_files = 20000 request_terminate_timeout = 10 pm.max_requests = 20000user,group也需要自定义化，打开文件/etc/nginx/nginx.conf ，看第一行user www-data，需与此值相同。4. 重启服务，更新配置：sudo systemctl restart nginx php7.4-fpm也可以将两个服务加入开机服务(disable取消）：sudo systemctl enable nginx php7.4-fpm5. 测试文件回到/opt/www目录，创建文件：sudo vim info.php<?php phpinfo(); ?>然后在浏览器输入：ServerIP/info.php即可看到6.可能错误排查查看错误日志// nginx tail /var/log/nginx/error.log // php systemctl status php7.4-fpm.service错误1：403，无文件或者权限不足无文件问题根据3.3节设置的index去看对应的文件夹是否有文件权限不足问题，则需要文件所有者账户将index的对应文件夹提权：sudo chmod R 777 /opt/www错误2：503 gateway error，一般是php-fpm配置出错，需注意配置文件不要写错位置（要自己找安装位置，一般在/etc或者/usr/local/etc中并且要从主配置文件顺藤摸瓜，找到include的文件位置，并在相应位置创建），另外配置listen端口一定需与nginx的pass端口相同。[tip type=""]教程一：[cid="25"][/tip]
安装Nginx：1.1sudo apt update sudo apt install nginx验证结果,使用命令：sudo systemctl status nginx若有结果如下则说明成功：但注意，此时只是在服务器上配置好了nginx，执行nginx -v应当可以看到版本号。此外，如果对nginx更新了配置，如增加了PHP解释，则应当重启nginx服务器：sudo systemctl restart nginx1.2但是从外界还是无法访问，所以我们还需要配置防火墙，使用UFW防火墙管理工具可以轻松完成：安装UFW：sudo apt-get install ufw -y启动UFW服务：sudo ufw enable(或者相反的，也可以关闭/重置防火墙,下面命令不在安装流程内，不要执行)sudo ufw disable sudo ufw reset注意：一定要先开启ssh端口的开放，不然下次连接就G了！！！连不上了！！！sudo ufw allow 22启动服务后，需要配置防火墙，使得局域网内其他IP地址可以访问服务器的 HTTP（80）和 HTTPS（443）端口sudo ufw allow 'Nginx Full'验证状态：sudo ufw status成功则会如下所示：测试连通性：在本地浏览器输入服务器IP地址，默认使用http端口，即可访问nginx默认界面：[tip type=""]教程二：[cid="26"][/tip]