flacファイルをm4aにタグやカバー画像などすべて変換する(Python)

ipadにflacを移行できなかったためpythonでm4aにする。
またflac-m4a変換だけはなくタグの情報等も編集する。
当方、初投稿、故にMarkdown記法適当です。見にくかったらすみません。

<h2>事前準備</h2>
ffmpegをPCにインストールする

https://ffmpeg.org/

上のサイトからダウソして、解凍。詳しいインストール方法は各自お調べください。
次にPythonのライブラリのpydubとmutagenをインストールする
```
pip install pydub
pip install mutagen
```
<h2>サンプルコード</h2>

```python:encode.py
#-*- coding:utf-8 -*-
import time, os, re
from pydub import AudioSegment
AudioSegment.converter = "C:\\ffmpeg\\bin\\ffmpeg.exe"
from mutagen.flac import FLAC, Picture
from mutagen.mp4 import MP4Tags, MP4, MP4Cover
from os import path

#flacのタグ名とm4aのタグ名に整合性を取る
def tag_flac_m4a(tag):
    match tag:
        case 'title':
            return "\xa9nam"
        case 'artist':
            return "\xa9ART"
        case 'albumartist':
            return 'aART'
        case 'tracknumber':
            return 'trkn'
        case 'date':
            return '\xa9day'
        case 'genre':
            return '\xa9gen'
        case 'album':
            return '\xa9alb'

class tag:
    def __init__(self, name, path_in, path_out=None):
        #インスタンス変数に値を入力
        self.name = name            #ファイル名を定義
        self.path_in = path_in      #元ファイルのディレクトリのパスを定義
        self.path_out = path_out    #出力ファイルのディレクトリのパスを定義
    
    #flacをm4a変換
    def convert_m4a(self, path_out=None): 
        path_out=self.path_out if path_out is None else None    #出力フォルダが定義されていなかったらインスタンス変数から取り出す
        import_path = self.path_in + self.name + '.flac'
        Audiodata = AudioSegment.from_file(import_path, 'flac')         #flacファイルの読み込み
        #m4aへエクスポート(タグはすべて消去される)
        export_path = path_out + self.name + '.m4a'             #ファイルのパスを定義
        Audiodata.export(export_path, format='ipod', codec='aac', bitrate='320k')   #エンコード
        print(f'{self.name}のエクスポートが完了しました。')
    
    #タグを抽出
    def get(self):
        audio_info = FLAC(self.path_in + self.name + '.flac')
        tagname_list = ['title','artist','albumartist','date','tracknumber','genre','album']
        tag_dict = dict()
        #タグの情報を辞書に格納{tag:info}
        for tagname in tagname_list:
            try:
                tag_temp = {tagname:audio_info.tags[tagname]}
            except KeyError:
                continue
            tag_dict = {**tag_dict, **tag_temp}
        self.tag_dict = tag_dict
        print('タグの抽出を完了しました。')
        return tag_dict

    def embed(self, path_out=None):
        path_out=self.path_out if path_out is None else None
        self.get()
        #m4aのタグを初期化
        tags = MP4Tags()
        for k,v in self.tag_dict.items():
            tagname = tag_flac_m4a(k)
            #トラック番号の場合 入力方法が異なる
            if tagname == 'trkn':
                v = re.findall(r'[0-9]+', v[0])
                if len(v)==2:
                    tags[tagname] = [(int(v[0]), int(v[1]))]
                else:
                    tags[tagname] = [(int(v[0]), int(v[0]))]
                continue
            tags[tagname] = v[0]
        tags.save(path_out + self.name + '.m4a')
        print('タグの埋め込みを完了しました。')

#海外の方から拝借
class cover(tag):
    #画像をflacファイルから抽出
    # '  https://stackoverflow.com/questions/67394817/from-flac-file-get-cover-image-and-display-it-on-a-tkinter-window  '
    def get(self):
        audio_file = self.path_in + self.name + '.flac'
        flacObj = FLAC(audio_file)
        coverArt = flacObj.pictures
        for img in coverArt:
            if img.type == 3:
                with open(f'cover_file\\{self.name}.jpg', "wb") as f:
                    f.write(img.data)
                print(f"{self.name}_cover.jpg の保存を完了しました。")

    #画像をm4aファイルに埋め込む
    #' https://python.hotexamples.com/jp/site/file?hash=0xf3bcb50e83333b6591172b93a6b1089b4f05105494cf35ac8c56441d132c78dd&fullName=musicgen.py&project=nejsan/sound_bubble '
    def embed(self, cover_file=None):
        """Embeds cover art into an audio file.
		Arguments:
			audio_file (str): The path to the audio file to embed the artwork in.
			cover_file (str): The path to the artwork file to embed.
		"""
        if cover_file is None:
            cover_file = f'cover_file\\{self.name}.jpg'
        audio_file = self.path_out + self.name + '.m4a'
        if path.isfile(audio_file) and path.isfile(cover_file):
            artwork = open(cover_file, "rb").read()
            # Determine which filetype we're handling
            if audio_file.endswith("m4a"):
                audio = MP4(audio_file)
                covr = []
                if cover_file.endswith("png"):
                    covr.append(MP4Cover(artwork, MP4Cover.FORMAT_PNG))
                else:
                    covr.append(MP4Cover(artwork, MP4Cover.FORMAT_JPEG))
                audio.tags["covr"] = covr
            audio.save()
            print(f'{self.name}のエクスポートを完全に完了しました。')
        else:
            with open('encoding.log', 'a', encoding='utf-8') as f:
                f.writelines('/cover:File is Not Found')

#glob.globのほうがいいかも
#変換したい音楽ファイルのディレクトリ
_in = "Music\\"
_out = "C:\\Documents\\music_m4a\\"
#ファイルの名前をリストに落とす
file_list = os.listdir(path=_in)
#flac拡張子のファイル名を抽出
flac_list = [s for s in file_list if '.flac' in s]
#拡張子を削除した名前リスト
name_list = [re.sub('.flac', '', name) for name in flac_list]

with open('encoding.log', 'w', encoding='utf-8') as f:
    for name in name_list:
        f.writelines(name + '\n')

if __name__=='__main__':
    for name in name_list:
        info = tag(name, path_in=_in, path_out=_out)
        with open('encoding.log', 'a', encoding='utf-8') as f:
            f.writelines('\n'+info.name)
        info.convert_m4a()
        info.get()
        info.embed()
        cover.get(info)
        cover.embed(info)

name_list = ['Perfect', 'Shape Of You']
#カバーを埋め込むだけ
if __name__ == '__main__':
    for name in name_list:
        info = tag(name, path_in=_in, path_out=_out)
        cover.embed(info, cover_file='divide.jpg')
```
質問や指摘や、効率のいいコードがあれば是非コメントをください。


<h2>参考</h2>

https://qiita.com/Dolphy_A/items/885315ddd7c5e2f487ef


https://www.wizard-notes.com/entry/python/mutagen-cheatsheet

https://www.wizard-notes.com/entry/python/extract_metatags_from_m4a_with_mudagen

https://programtalk.com/python-examples/mutagen.mp4.MP4Tags/

https://fossies.org/dox/metamorphose2_0.8.2/classmutagen_1_1mp4_1_1MP4Tags.html