navidrome里的专辑归纳还是有点乱。有些专辑下面只有一首歌,一个歌后若干个专辑(但下面只有一首歌)。等等这些问题,打算将部份id3信息清除或设置,达到管理专辑的目的。
经编译后使用:
查看信息: id3.exe -f 文件名
设置: id3.exe -f 文件名 -t 信息
清除: id3.exe -f 文件名 -c true -t 任意信息 (清除标题)
/*
修改Mp3 ID3信息的工具
2022.7.1
功能: aac文件转换为mp3(需ffmpeg)
修改mp3的ID3数据
查看mp3的ID3数据
*/
package main
import (
"flag"
"fmt"
"io/fs"
"io/ioutil"
"log"
"os/exec"
"path/filepath"
"runtime"
"strings"
"github.com/bogem/id3v2/v2"
)
func main() {
var File, nf string
var Artist, Title, Genre, Album, Year, Clear string
flag.StringVar(&File, "f", "", "文件")
flag.StringVar(&Artist, "a", "", "作者")
flag.StringVar(&Title, "t", "", "标题")
flag.StringVar(&Genre, "g", "", "类型/流派")
flag.StringVar(&Album, "l", "", "唱片集")
flag.StringVar(&Year, "y", "", "年")
flag.StringVar(&Clear, "c", "flase", "清除内容")
flag.Parse()
// 格式转换
if strings.ToLower(filepath.Ext(File)) == ".aac" {
f := []rune(File)
nf = string(f[0:len(f)-4]) + ".mp3"
fmt.Println("格式转换...")
Command([]string{"ffmpeg", "-i", File, "-acodec", "libmp3lame", nf})
} else {
nf = File
}
if File == "." {
for _, n := range FileForEach(".") {
if strings.ToLower(filepath.Ext(n.Name())) == ".mp3" {
fmt.Println("--------------------------------")
fmt.Println("文 件: ", n.Name())
setInfo(n.Name(), Artist, Title, Genre, Album, Year, Clear)
}
}
} else {
// 写ID3
setInfo(nf, Artist, Title, Genre, Album, Year, Clear)
}
}
func setInfo(f string, Artist, Title, Genre, Album, Year, Clear string) {
tag, err := id3v2.Open(f, id3v2.Options{Parse: true})
if err != nil {
fmt.Println("打开mp3文件出错: ", err)
return
}
defer tag.Close()
if Artist+Title+Genre+Album+Year == "" {
// 读取ID3
fmt.Println("a 作 者: ", tag.Artist()) // 作者
fmt.Println("t 标 题: ", tag.Title()) // 标题
fmt.Println("g 流 派:", tag.Genre()) // 类型/流派
fmt.Println("l 唱片集: ", tag.Album()) // 唱片集
fmt.Println("y 发 行: ", tag.Year()) // 年
} else {
if Clear == "true" {
// 清除ID3项内容
if Artist != "" {
fmt.Println("清除作者")
tag.SetArtist("")
}
if Title != "" {
fmt.Println("清除标题")
tag.SetTitle("")
}
if Genre != "" {
fmt.Println("清除流派")
tag.SetGenre("")
}
if Album != "" {
fmt.Println("清除唱片集")
tag.SetAlbum("")
}
if Year != "" {
fmt.Println("清除发行时间")
tag.SetYear("")
}
} else {
// 设置ID3
if Artist != "" {
fmt.Println("设置作者: ", Artist)
tag.SetArtist(Artist)
}
if Title != "" {
fmt.Println("设置标题: ", Title)
tag.SetTitle(Title)
}
if Genre != "" {
fmt.Println("设置流派: ", Genre)
tag.SetGenre(Genre)
}
if Album != "" {
fmt.Println("设置唱片集: ", Album)
tag.SetAlbum(Album)
}
if Year != "" {
fmt.Println("设置发行时间: ", Year)
tag.SetYear(Year)
}
}
}
if err = tag.Save(); err != nil {
fmt.Println("保存错误: ", err)
}
}
// 目录遍历
func FileForEach(fileFullPath string) []fs.FileInfo {
files, err := ioutil.ReadDir(fileFullPath)
if err != nil {
log.Fatal(err)
}
var myFile []fs.FileInfo
for _, file := range files {
if file.IsDir() {
continue
}
myFile = append(myFile, file)
}
return myFile
}
// 执行命令
func Command(params []string) (string, error) {
var c *exec.Cmd
switch runtime.GOOS {
case "darwin":
case "windows":
para := append([]string{"/C"}, params[0:]...)
c = exec.Command("cmd", para...)
case "linux":
para := append([]string{"-c"}, params[0:]...)
c = exec.Command("bash", para...)
}
output, err := c.CombinedOutput()
return string(output), err
}