APE Tags aus MP3s entfernen

  • Das folgende Script verwende ich, um sogenannte "APE" Tags aus MP3-Dateien zu entfernen. Für ID3 Tags gibt es ja bereits AutoIt UDFs. Dieses Script ist für die Verwendung von der Kommandozeile ausgelegt, daher ist es für die "Console" zu übersetzen.

    Das Script ist nur sehr grob getestet. Da die MP3s direkt geändert werden ist also Vorsicht angesagt. Besser Ihr macht eine Sicherheitskopie von den MP3s bevor ihr das Script darauf ansetzt.

    Spoiler anzeigen
    [autoit]

    #include <WinAPI.au3>

    [/autoit] [autoit][/autoit] [autoit]

    If $CmdLine[0]>0 Then
    Local $FileCnt
    For $FileCnt=1 To $CmdLine[0]
    RemoveAPE($CmdLine[$FileCnt])
    Next
    Else
    ConsoleWrite( _
    "Remove_APE" & @CRLF & _
    "Entfernt APE-Tags aus MP3-Dateien" & @CRLF & @CRLF & _
    "Anwendung:" & @CRLF & _
    "remove_ape.Exe <Dateiname1> [<Dateiname2> ....]" & @CRLF & @CRLF & _
    "Wildcards werden nicht erkannt." & @CRLF _
    )
    EndIf

    [/autoit] [autoit][/autoit] [autoit]

    #cs
    Entfernt APE Tags aus MP3-Dateien
    Achtung: Bitte vorher stets ein Backup der MP3-Dateien anlegen, da dieses Tool die Dateien auch
    zerstören könnte.

    [/autoit] [autoit][/autoit] [autoit]

    Vorgehen:
    APE Tags werden am Dateiende gesucht. Das ist eine Einschraenkung, aber zumindest die empfohlene
    Position.

    [/autoit] [autoit][/autoit] [autoit]

    Siehe:
    http://wiki.hydrogenaudio.org/index.php?titl…2_specification
    "an APE tag should be placed after the the last frame, just before the ID3v1 tag (if any)."

    [/autoit] [autoit][/autoit] [autoit]

    Dort koennen sich auch ID3V1 Tags befinden (Feste groesse 128 bytes)
    diese werden detektiert und ggf. nach dem Kuerzen erneut an die Datei angehaengt

    [/autoit] [autoit][/autoit] [autoit]

    APE Tags enden mit einem speziellen Footer. Dieser wird erkannt und es wird die Version und laenge gelesen.
    Ab Version 2000 gibt es noch einen Header welcher zur laenger hinzuaddiert wird.
    Da dieser Header (wie auch der Footer) einen speziellen Tag aufweist, wird daraus sicherheitshalber
    bei Version 2 (2000) auch geprueft.

    [/autoit] [autoit][/autoit] [autoit]

    #ce
    Func RemoveAPE($Filename)
    Local $hfile = FileOpen($Filename,16) ;open in binary mode

    FileSetPos($hfile,-128,2) ;#128 Bytes vom Dateiende (pruefe auf id3v1tag)
    Local $ID3v1Tag = FileRead($hfile)
    Local $EndOffs=0;

    Local $ID3v1ID = BinaryToString(BinaryMid($ID3v1Tag,1,3))

    ConsoleWrite("Remove_APE: " & $FileName & @CRLF)
    ;MsgBox(0,"ID3v1 Tag ID",$ID3v1ID)

    ;APE Header/Footer Laenge: 8(id) + 4(ver) + 4(len) + 4(num)+ 4(flags) + 8(res) = 32
    If ($ID3v1ID == "TAG") Then ;ID3v1 gefunden?, EndOffs Setzen und davor APE suchen
    $EndOffs=128
    ConsoleWrite(" ID3V1 Tags wurden erkannt (bleiben erhalten)" & @CRLF)
    Else
    $ID3v1Tag=""
    EndIf
    FileSetPos($hfile,-$EndOffs-32,2)

    [/autoit] [autoit][/autoit] [autoit]

    Local $APEFooter = FileRead($hfile,32)
    Local $APEID = BinaryToString(BinaryMid($APEFooter,1,8)) ;APETAGEX
    If ($APEID == "APETAGEX") Then
    Local $APEVer=Number(BinaryMid($APEFooter,9,4)) ;1000 oder 2000 (dez)
    Local $APELen=Number(BinaryMid($APEFooter,13,4));Laenge inkl Footer (bei APEV2: Laenge ohne Header)
    ;Local $APENumTags=Number(BinaryMid($APEFooter,17,4))
    If $APEVer>=2000 Then
    FileSetPos($hfile,-$EndOffs-$APELen-32,2)
    Local $APEHeader = FileRead($hfile,32)

    ;Man könnte noch auf TagFlag Bit 29 pruefen (1=Header, 0=Footer)
    ;Machichabbernich
    If ($APEID == "APETAGEX") Then
    $APELen=$APELen+32
    ConsoleWrite(" APE-Tags (v2) werden entfernt." & @CRLF)
    Else
    ConsoleWrite(" APE-Tags (v2 ohne Header) werden entfernt." & @CRLF)
    ;(Lt. Wikipedia ist der Header auch bei v2 optional, daher kein Fehler)
    ;$APELen=0
    ;ConsoleWrite("Fehler: APEV2 Footer ohne Header");Alternativ: ConsoleWriteError
    EndIf
    Else
    ConsoleWrite(" APE-Tags (v1) werden entfernt." & @CRLF)
    EndIf
    FileClose($hfile)

    If ($APELen>0) Then
    ;Datei verkuerzen
    TruncateFile($FileName,FileGetSize($FileName)-$EndOffs-$APELen)

    ;ID3v1 wieder anhaengen
    If BinaryLen($ID3V1Tag)>0 Then
    $hfile = FileOpen($Filename,17)
    ;FileSetPos($hfile,0,2)
    FileWrite($hfile,$ID3V1Tag)
    FileClose($hfile)
    EndIf
    EndIf
    Else
    ConsoleWrite(" Keine APE Tags in Datei" & @CRLF)
    FileClose($hfile)
    EndIf
    EndFunc

    Func TruncateFile($Filename,$NewLength)
    Local $hFile = _WinAPI_CreateFile($Filename, 2, 4)
    _WinAPI_SetFilePointer($hFile, $NewLength)
    _WinAPI_SetEndOfFile($hFile)
    _WinAPI_CloseHandle($hFile)
    EndFunc

    [/autoit]