PHP实现音乐列表json配置文件

8个月前 φ合肥 6

之前改了个静态网页播放器播放本地音乐的网站,当时就是用json配置文件收集音乐信息,只是收集上千首音乐信息比较复杂,是将数据输出到Excel表格,通过Excel公式实现的。最近感觉太麻烦了,想实现更简单的方法,最后从GPT3.5上得到了通过PHP实现这样的功能。

json数据格式

和之前是一样的。

[
{
"url":"URL地址",
"name":"歌曲名",
"artist":"歌手",
"lrc":"歌词地址URL"
},
{
"url":"URL地址",
"name":"歌曲名",
"artist":"歌手",
"lrc":"歌词地址URL"
},
{
"url":"URL地址",
"name":"歌曲名",
"artist":"歌手",
"lrc":"歌词地址URL"
}
]

功能代码PHP

//音乐文件所在的目录
$musicDirectory = 'Music';

function scanMusicDirectory($dir)
{
    $files = array_diff(scandir($dir), array('..', '.'));

    //初始化数组
    $musicFiles = array();

    //统计文件夹下音乐数量,因为一个音乐+一个歌词文件,所以得除以2
    $i = (count(scandir($dir)))/2;

    foreach ($files as $file) {

        $filePath = $dir . '/' . $file;

        //自定义歌曲网络路径
        $musicHttp = "https://alist.hjyl.org/";

        if (is_dir($filePath)) {
            //如果是目录,则递归扫描目录下的音乐文件
            $musicFiles = array_merge($musicFiles, scanMusicDirectory($filePath));
        } else if (pathinfo($filePath, PATHINFO_EXTENSION) == 'mp3' || pathinfo($filePath, PATHINFO_EXTENSION) == 'flac') {
            //如果是音乐文件,则将文件路径添加到数组中
            //通过分隔符获取音乐文件名
            $fileName = explode(".".pathinfo($filePath, PATHINFO_EXTENSION), $filePath);
            //通过分隔符获取演唱者
            $artist = explode(" - ", $fileName[0]);
            //通过分隔符获取歌曲名
            $name = explode("/", $artist[0]);
         
            $musicFiles[] = array('id' => $i--, 'url' => $musicHttp . $filePath, 'name' => $name[1], 'artist' => trim($artist[1], " "), 'lrc' => $musicHttp . $fileName[0].".lrc");

        }
        
    }

    return $musicFiles;
}

$musicFiles = scanMusicDirectory($musicDirectory);

//JSON_UNESCAPED_UNICODE解决中文乱码,JSON_UNESCAPED_SLASHES解决输出内容有反斜杠
$jsonData = json_encode($musicFiles, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);

//将生成的JSON数据写入到文件中
file_put_contents('music.json', $jsonData); 

echo 'JSON文件生成成功!';

将上面代码保存为music.php,设置音乐文件夹路径,既可以在浏览器中执行,又可以在SSH终端里执行。最后同目录下music.json文件就是所需要的配置文件了。只是这个歌曲顺序不太清楚是按什么顺序来的,前面字符、数字和英文是正常的升序,但是后面的中文就有点乱来了,不过不一样,比我手动编辑快多了。

关于getid3

PHP有一个脚本可以提取文件标签信息,包括音频、视频,它叫getID3()。所以如果用这个脚本,功能代码是这样的。当然前提是你将getid3脚本文件拷到当前文件夹下,然后才能调用。

//音乐文件所在的目录
$musicDirectory = 'Music';

require_once "./getid3/getid3.php";
require_once "./getid3/getid3.lib.php";
function scanMusicDirectory($dir)
{
$files = array_diff(scandir($dir), array('..', '.'));

//初始化数组
$musicFiles = array();

//统计文件夹下音乐数量,因为一个音乐+一个歌词文件,所以得除以2
$i = (count(scandir($dir)))/2;

foreach ($files as $file) {

$filePath = $dir . '/' . $file;

//自定义歌曲网络路径
$musicHttp = "https://alist.hjyl.org/";

if (is_dir($filePath)) {
//如果是目录,则递归扫描目录下的音乐文件
$musicFiles = array_merge($musicFiles, scanMusicDirectory($filePath));
} else if (pathinfo($filePath, PATHINFO_EXTENSION) == 'mp3' || pathinfo($filePath, PATHINFO_EXTENSION) == 'flac') {
//如果是音乐文件,则将文件路径添加到数组中
//通过分隔符获取音乐文件名
$fileName = explode(".".pathinfo($filePath, PATHINFO_EXTENSION), $filePath);

//调用getid3方法
$getID3 = new getID3;
$music = $getID3->analyze($filePath);
$musicFiles[] = array('id' => $i--, 'url' => $musicHttp . $filePath, 'name' => $music["comments"]["title"][0], 'artist' => $music["comments"]["artist"][0], 'lrc' => $musicHttp . $fileName[0].".lrc");
}

}

return $musicFiles;
}

$musicFiles = scanMusicDirectory($musicDirectory);

$jsonData = json_encode($musicFiles, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);

//将生成的JSON数据写入到文件中
file_put_contents('music.json', $jsonData);

echo 'JSON文件生成成功!';

不过可惜的是,无论是在浏览器还是终端中执行,两种方法都不是很完美。如果是在浏览器中执行,音乐文件和PHP需要处在同一级别目录,或者音乐文件处在PHP下一级目录都可以,但是我的音乐文件是在另一个磁盘里,浏览器获取不到路径权限,而这个在终端里执行却是可以的。但是终端又只能运行单PHP文件,而获取不到getid3脚本功能。所以最后我还是放弃了这个脚本。

其实用这个脚本,主要还是获取音乐封面,我收集的都是无损音乐,主要是flac格式,还有一小部分mp3格式,但是都内置有封面信息。如果可以直接提取,我就不用再通过js提取了。不过二者结果是一样的。而且js可以将base64图片地址转换为blob地址,PHP却不行,后来了解到blob链接只是浏览器内部生成的临时链接,不能被保存到文件,更不能被永久读取,所以就更不需要getid3脚本了。只是base64编码地址太长了,整套下来,终端都崩溃了。于是封面还是保留了之前的处理方式。

上面的代码仅供参考吧!

6 条评论

  1. #1

    很好很高级!学习了。

    • @织梦岁月 如果把音乐文件丢进去,自动生成配置文件,或者播放器直接能读取文件数据就更好了

  2. #2

    web 播放器播放本地音乐?还是服务器上的音乐?

  3. #3

    这种方法好厉害,羡慕了,我也搞搞,哈哈

    • @段先森 GPT 还是很厉害的,代码差不多,稍微懂一些,再修改修改就好了。就怕不理解我的意思,而且国内的很多接口都只能问几次,然后就要收费了。