2012-05-31 2 views
1

내 MP3 파일 이름을 읽는 Python 스크립트를 작성하려고하는데 누락 된 아티스트 태그를 찾으면 파일 이름의 첫 번째 부분부터 가져옵니다. 대부분의 MP3 파일은 "아티스트 - Title.mp3"이라는 제목이 붙어 있습니다.Python의 ID3 태그 - Python이이 작업에 잘못된 언어입니까?

그러나 ID3 태그 리더는 Python에서 잘 작동하지 않습니다. ID3는 1.1 이후에는 태그를 읽지 않으며 2002 년 이후로 개발되지 않았습니다. 파일에 태그가 누락되면 Mutagen에서 예외가 발생합니다. Eye3D는 pylibid3와 함께 작동하도록 라이브러리를 설치하려면 바이너리를 설치해야합니다.

잘못된 언어를 사용하고 있습니까? Perl에 훌륭한 ID3 태그 라이브러리가 있다고 들었습니다. 나는 초보자이기 때문에 언어 전환 (Perl에 대한 책을 읽은 이후로 오랜 시간이 걸렸습니다)은 처음부터 다시 시작하는 것을 의미합니다. 하지만 파이썬이 잘못된 언어라면 기꺼이 할 것입니다.

의견이 있으십니까?

+0

펄 CPAN의 libraies을 검색하려면 : – toolic

+1

빠른 구글이 나왔고 http://search.cpan.org/search?query=mp3&mode=all : http://wiki.python.org/moin/UsefulModules # ID3_Handling. 이 모든 모듈을 고려해 보셨습니까? –

+2

Mutagen에 머무르다, 그것은 현재 최고의 ID3 라이브러리입니다. 나는 예외적으로 (하하) 잘 작동한다는 것을 알게된다. 펄 (Perl) 지역의 어떤 것보다 좋고 심지어 taglib 바인딩도 좋다. 예외는 Python에서 흔히 볼 수있는 예외입니다. 예외를 잡아 원하는대로 계속하십시오. – daxim

답변

4

이 돌연 변이와 예외를 처리하기 위해 쉽게 충분 :

from mutagen.id3 import ID3, TPE1, ID3NoHeaderError 
try: 
    audio = ID3(filename) 
except ID3NoHeaderError: 
    audio = ID3() 

audio.add(TPE1(encoding=3, text=u'Artist')) 
audio.save(filename) 
+0

참. 나는 그것을 시도 할 것이다, 고마워. Mutagen을 사용하여 예외가 생겼을 때 벽돌 벽에 부딪쳤다 고 느꼈습니다. – Tensigh

+0

작동하지 않는 것 같아요. mutagen.id3.ID3NoHeaderError : 'E : \ .mp3'이 ID3 태그로 시작하지 않습니다. – Tensigh

+0

@Tensigh, 놀랍습니다. – xorsyst

0

여기 당신이 원하는 않는 펄 스크립트입니다. 나는 이것을 항상 사용한다. 또한 변경하기 전에 변경 사항을 미리 봅니다.

몇 가지 Perl 모듈 (MP3 :: Info 및 MP4 :: Info)을 설치해야하지만 코드에서 MP4 행을 제거하고 해당 모듈을 건너 뛸 수는 있습니다.

#!/usr/bin/perl 

use strict; 
use warnings; 
use Cwd; 
use File::Copy; 
use File::Basename; 

# Load MP3/MP4 modules and set them up to use UTF-8 characters 
# (Unicode-like support, to see accents, etc.). 
use MP3::Info qw(:all); 
use_mp3_utf8(1); 
use MP4::Info qw(:all); 
use_mp4_utf8(1); 

my @ARGS; 
################################################################################ 
# Subroutine: RemoveIllegalFilenameCharacters 
# Inputs:  $filename 
# Outputs: $filename 
################################################################################ 
sub RemoveIllegalFilenameCharacters { 
    my $filename = shift; 

    if ($filename =~ m/\\/) { $filename =~ s/\\//g } 
    if ($filename =~ m/\//) { $filename =~ s/ \//- /g } 
    if ($filename =~ m/\//) { $filename =~ s/\///g } 
    if ($filename =~ m/:/) { $filename =~ s/://g } 
    if ($filename =~ m/\*/) { $filename =~ s/\*//g } 
    if ($filename =~ m/\?/) { $filename =~ s/\?//g } 
    if ($filename =~ m/"/) { $filename =~ s/"//g } 
    if ($filename =~ m/</) { $filename =~ s/<//g } 
    if ($filename =~ m/>/) { $filename =~ s/>//g } 
    if ($filename =~ m/\|/) { $filename =~ s/\|//g } 

    return $filename; 
} 

################################################################################ 
# Subroutine: Rename 
# Inputs:  $test (indicates test mode) 
# Outputs: number of files to be changed (in test mode) 
################################################################################ 
sub Rename { 
    my $test = shift; 
    my $destDir = ""; # hard-coded permanent destination, if desired 

    my @tests; 
    foreach my $file (@ARGS) { 
    # Get rid of the Mac OS resource fork files. 
    if ($file =~ m/^\._/) { 
     unlink "$file"; 
     next; 
    } 

    if (! -f $file) { 
     warn "'$file' does not exist!\n"; 
    } 
    else { 
     # If $destDir wasn't set above, then that means it should be 
     # set to the original dir of each file. 
     if (!($destDir)) { 
    $destDir = dirname($file); 
     } 

     my $extension = $file; 
     $extension =~ s/.*\.//; 

     my $tag; 
     if ($extension =~ m/^mp3$/i) { 
    ($tag = get_mp3tag($file)) || warn "'$file' does not contain ID3 tags (it may not even be an MP3 file!)\n"; 
     } 
     else { 
    # If it's not MP3, try MP4 
    ($tag = get_mp4tag($file)) || warn "'$file' does not contain ID3 tags (it may not even be an AAC/M4A/M4P file!)\n"; 
     } 
     if (!($tag)) { 
    # No $tag was returned. Go to the next $file. 
    next; 
     } 

     # DEBUG! Show all the tag names. Could be modifed to show all the tag values too. 
     if (0) { 
    print join("\n", keys %{$tag}) . "\n"; 
     } 

     # Set the rename format depending on if we're under the $DOWNLOAD_DIR or not. 
     my $newFile = $$tag{"ARTIST"} . " - " . $$tag{"TITLE"} . ".$extension"; 

     if (($$tag{"ARTIST"} eq "") || ($$tag{"TITLE"} eq "")) { warn "\n*** WARNING! This track is missing some info:\n\tOriginal Name: $file\n\tNew Name: $newFile\n\n" } 
     $newFile = RemoveIllegalFilenameCharacters($newFile); 

     # If current filename ($file) already matches the new filename ($newFile), 
     # don't bother continuing (filename is already in the correct format). 
     if ($file eq $newFile) { 
    # If we're not choosing to move all files, 
    # and if the filename is already in the correct format, 
    # go to the next $file. 
    next; 
     } 
     if ($destDir ne ".") { $newFile = $destDir . "/" . $newFile } 
     if (!($test) && -f $newFile) { 
    die "Unable to move '$file' to '$newFile',\nsince there's already a file named '$newFile'!\nStopped"; 
     } 
     if ($test) { 
    push @tests, $newFile; 
     } else { 
    print "Moving '$file' to '$newFile'\n"; 
    move($file, $newFile) || die "Unable to move file!\n"; 
     } 
    } # End of if-then-else checking if file exists 
    } # End of FOR loop looping through files in @ARGS. 

    if ($test && scalar(@tests)) { 
    print "Test run - new filenames: \n "; 
    print join("\n ", sort(@tests)); 
    } 

    return scalar(@tests); 
} 

################################################################################ 
# MAIN ROUTINE 

if (scalar(@ARGV) == 0) { 
    # If no args, use every music file in current directory. 
    opendir(DIR, "."); 
    @ARGS = sort(grep(/\.mp3$|\.aac$|\.m4a$|\.m4p$/i, readdir(DIR))); 
    closedir(DIR); 

    if (scalar(@ARGS) == 0) { 
     print "USAGE: " . basename($0) . " <music-files>\n\n"; 
     print "If no filenames are specified, any music files (MP3/AAC/M4A/M4P) in the current directory will be used.\n"; 
     exit 1; 
    } 
} 
else { @ARGS = @ARGV } 

if (Rename(1)) { 
    print "\n\nDo the test results look good?\n"; 
    print " n - No they don't. Do not rename the files!\n"; 
    print "[y] - Yes they do. Rename the files and leave them in their original folder(s).\n"; 
    print " "; 
    my $choice = <STDIN>; 
    chomp $choice; 
    # Only do the move if we're in the $DOWNLOAD_DIR area. 
    # This allows us to use the default (null) response to process renames in a non-download dir. 
    if (("$choice" eq "") || ("$choice" eq "y")) { 
    Rename(0); 
    } 
} 
else { 
    print "No actions needed.\n"; 
} 
+0

감사합니다. 나는 Perl을 설치했지만 모든 에너지를 파이썬에 쏟아 부었다. 내가 이것을 시작한 이유 중 하나는 프로그래밍을 배우는 것이 었습니다. 나는 Perl에서 좋은 것들을 많이 보았고 Perl을 픽업하도록 동기를 부여 받았다. 스크립트를 가져 주셔서 감사합니다. – Tensigh