简介:MKOnlinePlayer v2.4修复版是一套基于PHP的在线音乐播放器源码,面向网站管理员、个人站长与PHP开发者,用于在浏览器端搭建无需客户端的自定义音乐播放功能,适合个人博客或中小型音乐站点快速集成。压缩包共39个文件,约235KB,以10个js脚本承担播放控制、歌词滚动、歌单管理与AJAX交互,5个css与7个png、6个jpg、4个gif负责界面样式和封面图标,另有3个html页面、2个php接口文件及README说明,结构紧凑便于二次开发。资源已有620人学习下载。功能上覆盖歌曲列表管理、播放暂停与进度拖动、搜索、顺序/随机/单曲循环模式及界面定制,修复版针对播放中断、加载失败做了稳定性改进,并优化加载速度、浏览器兼容性与代码安全性。读者可据此快速部署LAMP或WAMP环境、配置数据库与目录权限,并参考插件目录与Meting接口进行皮肤替换或功能扩展。
1. 一个 PHP 音乐播放器源码,为什么还有人愿意折腾
PHP 在线音乐播放器源码 MKOnlinePlayer v2.4 修复版,这个标题里其实藏着三类人的真实需求。第一类是手里有台便宜虚拟主机、只想放几十首歌自己听的人,他们不需要流媒体平台那套推荐算法,只需要一个能列出歌单、点开就播、手机浏览器也能用的页面。第二类是想拿现成源码练手 PHP 文件读写和前端音频 API 的开发者,他们关心的是代码结构清不清楚、能不能二次改。第三类是做小型内部站点的人,比如工作室、社团、小团队,想在内网挂一个共享歌单,不依赖外部服务。
这个修复版的价值不在“播放器”三个字,而在于它把老版本里几个常见的坑补掉了:中文文件名乱码、移动端点击没反应、歌单扫描路径写死、播放进度条拖动跳回。这些不是玄学,是 PHP 处理文件路径和前端 audio 事件绑定的老问题。下面按“先跑起来、再改得动、最后不翻车”的顺序拆。
2. 把源码跑起来:环境、目录和第一次访问
2.1 虚拟主机和 PHP 版本怎么选
这类播放器本质是 PHP 扫目录 + 输出 JSON 歌单 + 前端 audio 标签播放。它对环境要求很低,但有几个硬条件:
- PHP 5.6 到 7.4 最稳,PHP 8 以上要注意
each()这类老函数被移除的问题。修复版一般会处理,但拿到源码后先搜一遍each(、split(、ereg(。 - 不需要数据库,歌单靠扫描音乐目录生成。所以虚拟主机必须允许 PHP 读取你上传的音乐文件夹。
- 需要
json_encode、scandir、file_get_contents这几个函数没被禁用。有些便宜主机为了安全会禁scandir,那就直接跑不起来。
常见做法是本地先用 PHP 内置服务器验证,再上传。命令如下:
# 在源码根目录执行,-t 指定入口目录,8080 是端口 php -S 0.0.0.0:8080 -t ./逻辑说明:-t ./把当前目录当网站根目录,这样index.php和music/的相对路径关系和你上传到虚拟主机后一致。参数说明:端口被占用就换 8081;如果本地 PHP 没装,用 XAMPP 或 phpStudy 这类集成环境也行,但要注意它们默认的 PHP 版本。
2.2 目录结构:音乐放哪里、歌单怎么生成
修复版通常保留这样的结构:
mkplayer/ ├── index.php # 入口页面 ├── api.php # 输出歌单 JSON ├── static/ │ ├── css/ │ └── js/ └── music/ # 音乐文件目录 ├── 华语/ ├── 欧美/ └── 纯音乐/关键在api.php里扫描music/的逻辑。很多老版本写死只扫一层,子目录里的歌出不来。修复版一般改成递归扫描。你可以先手动放三首歌进music/,然后直接访问http://你的域名/api.php,看返回的 JSON 里有没有这三首。
<?php // api.php 核心扫描逻辑示意 $root = __DIR__ . '/music'; $list = []; // 递归扫描,支持子目录 $it = new RecursiveIteratorIterator( new RecursiveDirectoryIterator($root, FilesystemIterator::SKIP_DOTS) ); foreach ($it as $file) { // 只取常见音频后缀,避免把封面图也扫进去 if (in_array(strtolower($file->getExtension()), ['mp3', 'm4a', 'flac', 'wav'])) { $list[] = [ 'name' => $file->getBasename('.' . $file->getExtension()), 'path' => str_replace(__DIR__, '', $file->getPathname()), 'size' => $file->getSize(), ]; } } header('Content-Type: application/json; charset=utf-8'); echo json_encode($list, JSON_UNESCAPED_UNICODE);逻辑说明:RecursiveDirectoryIterator配合RecursiveIteratorIterator能一次拿到所有层级文件,比手写递归稳。参数说明:SKIP_DOTS跳过.和..;JSON_UNESCAPED_UNICODE保证中文歌名不变成\uXXXX。注意str_replace(__DIR__, '', ...)得到的是相对路径,前端拼接播放地址时要用这个相对路径,不要用绝对路径,否则换域名就废。
2.3 第一次访问要检查的三件事
第一,浏览器控制台有没有 404。通常是static/js/里的文件路径大小写问题,Linux 主机区分大小写,Windows 本地不区分,上传后就翻车。第二,点播放没声音,看 Network 里音频请求是不是 206 或 200,如果是 403 说明音乐目录权限不对,目录给 755、文件给 644。第三,歌单是空的,直接访问api.php看返回,如果是[]就检查music/里是不是真的放了音频文件,以及后缀有没有被过滤掉。
3. 改得动:歌单格式、播放器参数和移动端适配
3.1 歌单 JSON 字段怎么和前端对齐
前端拿到的每条歌单至少要有三个字段:显示名、播放地址、可选的封面。修复版常见字段是name、path、cover。如果你自己加字段,比如artist、album,要同步改前端渲染逻辑,否则列表里不显示。
// static/js/player.js 里渲染歌单的片段 fetch('api.php') .then(res => res.json()) .then(list => { const box = document.getElementById('list'); list.forEach((item, i) => { const div = document.createElement('div'); div.className = 'song-item'; //>let isSeeking = false; audio.addEventListener('seeking', () => { isSeeking = true; }); audio.addEventListener('seeked', () => { isSeeking = false; }); audio.addEventListener('timeupdate', () => { // 用户正在拖动时不要回写进度条,否则会跳回 if (!isSeeking) { progress.value = audio.currentTime; } });逻辑说明:seeking在拖动开始时触发,seeked在拖动结束触发,用标志位隔离两个状态。参数说明:progress是进度条元素,value用秒数还是百分比取决于你的max设置,保持一致即可。
4. 避坑与排查:五个真实会遇到的翻车点
4.1 中文歌名变成乱码或问号
现象:歌单里中文显示为????或海风。原因:PHP 文件本身编码不是 UTF-8,或者json_encode没加JSON_UNESCAPED_UNICODE,再或者 HTML 的meta charset写成了gb2312。解决:统一三处编码——PHP 文件存为无 BOM 的 UTF-8、json_encode加JSON_UNESCAPED_UNICODE、HTML 里写<meta charset="utf-8">。三处缺一处都可能乱。
4.2 扫描目录返回空数组
现象:api.php返回[],但music/里明明有歌。原因:open_basedir限制、scandir被禁用、或者路径用了相对路径但当前工作目录不对。解决:用__DIR__拼绝对路径,先var_dump(is_dir($root))确认目录存在,再var_dump(scandir($root))看函数是否可用。如果scandir被禁,改用glob或DirectoryIterator。
4.3 播放到一半卡住或 206 请求失败
现象:歌能播几秒然后停,Network 里音频请求状态是 206 但后续没继续。原因:虚拟主机不支持 Range 请求,或者 PHP 输出音频时没处理Range头。解决:这类播放器一般让 Web 服务器直接伺服音频文件,不走 PHP 读文件输出。确认音频 URL 是直接指向music/xxx.mp3,而不是play.php?id=xxx。如果必须走 PHP,要手动解析HTTP_RANGE并返回 206 和Content-Range。
4.4 上传后首页空白但本地正常
现象:本地php -S正常,上传到主机后白屏。原因:PHP 版本差异导致语法错误,或者short_open_tag没开导致<?被当文本。解决:看主机错误日志,把<?全部改成<?php,检查有没有用 PHP 8 移除的函数。临时开display_errors看报错,但排查完记得关掉。
4.5 歌单顺序每次刷新都不一样
现象:同一批歌,刷新后顺序变了。原因:scandir和RecursiveDirectoryIterator的返回顺序依赖文件系统,不保证稳定。解决:拿到数组后按文件名sort()或按修改时间usort()排一次。如果想让用户自定义顺序,就得引入一个order.json存排序,不能靠目录顺序。
5. 进阶:把播放器改成能长期维护的小系统
跑到这里,基础播放已经没问题了。但如果你打算长期用,有几个技巧值得加。第一,给api.php加一层缓存。每次刷新都扫目录,歌多了会慢。用文件缓存把 JSON 存下来,目录修改时间变了再重新扫:
$cacheFile = __DIR__ . '/cache/list.json'; $musicDir = __DIR__ . '/music'; // 目录最后修改时间晚于缓存文件,才重新扫描 if (!file_exists($cacheFile) || filemtime($musicDir) > filemtime($cacheFile)) { $list = scanMusic($musicDir); // 你的扫描函数 file_put_contents($cacheFile, json_encode($list, JSON_UNESCAPED_UNICODE)); } else { $list = json_decode(file_get_contents($cacheFile), true); }逻辑说明:用目录修改时间做缓存失效判断,比定时任务简单。参数说明:cache/目录要可写,且不能被外部访问到,最好在 Web 根目录外,或者加.htaccess拒绝访问。
第二,给播放地址加签名或 token,防止别人直接扒你的音频文件。简单做法是在api.php生成带过期时间的链接,播放时校验。第三,移动端加媒体会话 API,让锁屏界面显示歌名和封面:
if ('mediaSession' in navigator) { navigator.mediaSession.metadata = new MediaMetadata({ title: currentSong.name, artist: '未知', album: '在线歌单', artwork: [{ src: currentSong.cover || 'static/cover.png', sizes: '512x512', type: 'image/png' }] }); }逻辑说明:MediaMetadata让系统锁屏和通知栏显示歌曲信息,不设的话锁屏只显示“未知”。参数说明:artwork的sizes要和实际图片尺寸匹配,否则部分安卓机不显示。
我自己的习惯是,拿到任何一份老 PHP 源码,先不急着改功能,而是把api.php单独跑通、把返回 JSON 打印出来看一遍。这一步花十分钟,能省掉后面两小时的瞎猜。MKOnlinePlayer 这类播放器的修复版,核心价值就是把文件扫描和前端事件这两条线理顺了,剩下的都是在这个骨架上加肉。希望帮到你。
本文还有配套的精品资源,点击获取