(原) mp3信息设置工具

原创文章,请后转载,并注明出处。

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
}

相关文章