perl で mp3 の歌詞を自動で入れたい。改良。
動かし方:フォルダーに mp3 を入れて起動。perl filegetlyricsJ.pl "/mnt/d/music/mp3/test/"
mp3 の tag の曲名とアーティスト名から、歌詞をとってきます。
ただ、取りに行っているサイトの関係で、日本の歌ぐらいしか取れてません。
環境:windows10 に ubuntu を入れて実行してます。
$ sudo apt-get install libmp3-tag-perl
とかで、モジュールは追加。
習作ですがとりあえず公開。
------------------------------- filegetlyricsJ.pl の名前で以下を保存
#!/usr/bin/perl
# 日本語EUC-JP、LF
use strict;
use warnings;
use Data::Dumper;
use Jcode;
use Encode;
use URI::Escape;
use LWP::Simple;
use MP3::Tag;
use File::Basename;
die "Please specify folder" if ( $#ARGV < 0 );
while ( my $path = shift @ARGV ) {
chdir($path);
my @files = glob "*.mp3";
foreach my $f (@files){
print "try $f \n";
my $result = GetLyrics( $f )
}
}
sub GetLyrics {
my $file = shift @_;
my $lyr = GetInferedLyrics( $file )
or warn "32 Lyrics not found for " . basename( $file );
# 歌詞がないと戻る
return if ( !$lyr );
#歌詞を見るとき
#print "$lyr \n";
#text file 書き出し
# my $txtWrite = WriteWriteLyrics($file,$lyr);
#mp3 処理
my $mp3 = MP3::Tag->new( $file ) or return; # エラー
print "44 $file \n";
$mp3->select_id3v2_frame_by_descr("USLT(eng)", $lyr); # 歌詞
$mp3->update_tags();
$mp3->close;
warn "All done ----- $file";
return $file
}
#text file 書き出し
sub WriteWriteLyrics {
my $file = shift @_;
my $lyr = shift @_;
my $txtFile = $file;
$txtFile =~ s/\.mp3$/.txt/i;
open( W, ">" . $txtFile ) or next;
binmode W;
print W $lyr;
close( W );
return $txtFile;
}
sub GetInferedLyrics {
my $file = shift @_;
# tag 取得
my( $title, $art ) = GetFuzzyID3Tags( $file ) or return; # エラー
# 歌詞取得
my @list = GetCandidates(
$art,
$title
);
print "77 $art\n";
print "78 $title\n";
# エラー
# Space を + にして実行
if ( $#list != 0 ){
$art =~ s/\s/\+/g;
@list = GetCandidates($art,$title);
}
if ( $#list != 0 ){
$title =~ s/\s/\+/g;
@list = GetCandidates($art,$title);
}
if ( $#list != 0 ){
$art =~ s/\s/\+/g;
$title =~ s/\s/\+/g;
@list = GetCandidates($art,$title);
}
# 全角 を 半角 にして実行
if ( $#list != 0 ){
$art = jcode($art)->tr('A-Za-z0-9@・','A-Za-z0-9@-');
$title = jcode($title)->tr('A-Za-z0-9@・','A-Za-z0-9@-');
@list = GetCandidates($art,$title);
}
# エラー
if ( $#list != 0 ){return;}
#歌詞取得
return $list[0]->{head} ;
}
sub GetFuzzyID3Tags {
my $file = shift @_;
my( $title, $art ) = GetID3Tags( $file ) or return; # エラー
$title =~ s/\(.*?\)//g;
$art =~ s/\(.*?\)//g;
return( $title, $art );
}
sub GetID3Tags {
my $file = shift @_;
my $mp3 = MP3::Tag->new( $file ) or return; # エラー
my( $title, $track, $art ) = $mp3->autoinfo() or return; # エラー
#歌詞がすでに入っているか取得
my $lyric = $mp3->select_id3v2_frame_by_descr("USLT(eng)");
$mp3->close;
#歌詞がすでに入っているときは飛ばす
if ($lyric){
$title = "Lyrics already exist"; #エラーにする
return;
}
$title =~ s/\t/ /g;
$art =~ s/\t/ /g;
my $str = "$title\t$art";
$str =~ s/-/-/g;
return( split( /\t/, $str ) );
}
sub GetCandidates {
my $art = shift @_;
my $title = shift @_;
my $baseurl = 'https://utaten.com/lyric/';
my $url = $baseurl . '%ART%/%TITLE%';
my $head = '%ART%:%TITLE%';
$title = uri_escape_utf8($title);
$url =~ s/\%ART\%/$art/;
$url =~ s/\%TITLE\%/$title/;
print "155 $url \n";
# LWP::Simpleの「get」関数を使用
my $html = get($url) or die "Couldn't get it!";
my $kashi="";
while ($html =~ /(.*span.*)/mg) {
$kashi = $kashi . $1;
}
# 歌詞だけに変換
$kashi =~ s/\<br.\/\>/\n/mg;
$kashi =~ s/rt.*?\<//mg;
$kashi =~ s/\<.*?\>//mg;
$kashi =~ s/.*UtaTen/\n/mg;
$kashi =~ s/\s\s/\n/mg;
$kashi =~ s/\n{3,20}/\n/g;
#歌詞なし
my $count = () = $kashi =~ m/New\!\!/g;
if ($count > 4) {return}
my $this;
$this->{url} = $baseurl;
$this->{title} = $title;
$this->{head} = "";
$count=1;
my @lines = split m{\n}, $kashi;
my $frm = decode('euc-jp','の歌詞');
foreach my $line ( @lines ) {
# 一行ずつ処理
if ($count != 3){
if ($count <5 ){$line=~ s/$frm//;}
$this->{head} = $this->{head} . $line . "\n";
}
$count = $count + 1;
}
my @candidates;
push( @candidates, $this );
return @candidates;
}
0 件のコメント:
コメントを投稿