使用 Taglib-Sharp 操作 UserDefined 标签(TXXX 帧)

Manipulate UserDefined tag (TXXX frame) with Taglib-Sharp

形势任务

我有一个大音乐collection,我想清理他们ID3V2 tags with PowerShell and taglip-sharpcommentencoding 等标签应删除,而 artisttitle 等其他标签则不应删除。

Usually you manipulate ID3 tags this way (Simplified version)

# Add taglib dll 
[Void][System.Reflection.Assembly]::LoadFrom("$PSScriptRoot\taglib-sharp.dll")

# Load example mp3 into memory as [taglib.file]
$media = [TagLib.File]::Create("C:\path\to\musicFile.mp3")

# Change comment tag 
$media.tag.tags[0].Comment = "Hello World"

# Save tags back to mp3 file
$Media.Save()

问题

许多音乐文件在帧 called TXXX 中存储自定义信息,如 URLShop Name。不幸的是,无法使用上面显示的方法访问此框架。或者我还没有找到办法

相反,您使用

# Read UserTextInformationFrame
$media.GetTag([TagLib.TagTypes]::Id3v2).GetFrames("TXXX")

这个User defined text information frame可以保存多个值。有些很有用,因为像 Foobar 这样的音乐播放器会在 TXXX 中存储 PERFORMERDATEreplay_track_gain 标签。

上面一行的示例输出可以是:

Description  : replaygain_track_gain
Text         : {-5.00 dB}
FieldList    : {-5.00 dB}
TextEncoding : Latin1
FrameId      : {84, 88, 88, 88}
Size         : 32
Flags        : None
GroupId      : -1
EncryptionId : -1

Description  : URL
Text         : {www.amazon.com}
FieldList    : {www.amazon.com}
TextEncoding : UTF16
FrameId      : {84, 88, 88, 88}
Size         : 43
Flags        : None
GroupId      : -1
EncryptionId : -1

在此之后,我能够过滤掉所有不必要的 TXXX 值

# Create a whitelist of TXXX frames
$goodTXXX  = 'performer','replaygain_track_gain','date'

# Read UserTextInformationFrame AND filter it
$newTXXX = $Media.GetTag([TagLib.TagTypes]::Id3v2).GetFrames("TXXX") | 
  where { $goodTXXX -contains $_.Description }   

问题:如何将多个值写入TXXX

所以我的问题是,如何将过滤后的结果保存回 mp3 文件?
我失败的尝试是:

$media.GetTag([TagLib.TagTypes]::Id3v2).RemoveFrames("TXXX")
$media.GetTag([TagLib.TagTypes]::Id3v2).SetTextFrame("TXXX",$newTXXX)
# Removes old values, but does not show anything in Foobar

#$media.GetTag([TagLib.TagTypes]::Id3v2).GetFrames("TXXX").SetText("Hello World")
# Shows garbage in Foobar. And it's not usable for multiple values

Taglib-Sharp documentation for SetTextFrame


奖励问题: taglib-sharp 是否能够在将新标签保存为 ID3v2.3 标签的同时去除 Id3v1 和 ID3v2.4 标签? (Related SO answer, but doesn't distinguish between v2.3 and v2.4)

我找到了尝试错误的方法。这并不优雅,因为如果您只想更改一个值,则必须删除所有 TXXX 值并将它们添加回去

# Add taglib dll 
[Void][System.Reflection.Assembly]::LoadFrom("$PSScriptRoot\taglib-sharp.dll")

# Load example mp3 into memory as [taglib.file]
$media = [TagLib.File]::Create("C:\path\to\musicFile.mp3")

# Get or create the ID3v2 tag.
[TagLib.Id3v2.Tag]$id3v2tag = $media.GetTag([TagLib.TagTypes]::Id3v2, 1)

# Create new 'TXXX frame' object
$TXXXFrame = [TagLib.Id3v2.UserTextInformationFrame]("WWW")

# Delete complete TXXX frame first, or else all values are just appended
$id3v2tag.RemoveFrames("TXXX")

# Set the value/text in the newly created TXXX frame, default Text encoding is UTF8
# Use curly brackets instead of single quotation marks
$TXXXFrame.Text = {www.myurl.com}

# Add TXXX frame to tag
$id3v2tag.AddFrame($TXXXFrame)

# Write all changed tags back to file
$media.Save()