形式
Perl
投稿日時
2017-09-02 16:18
公開期間
無期限
  1. #!/usr/bin/perl
  2. use warnings;
  3. use strict;
  4. use utf8;
  5. use Encode;
  6. use open ":locale";
  7. sub usage{
  8. print << "EOT"
  9. usage: $0 CUEFILE.cue [:ENCODING] [WAV-OVERRIDE] [+FORMAT] [- FFMPEG-OPTIONS...]
  10. Encoding:
  11. This is PerlIO layer selector.
  12. You can use :encoding(CHARCODE) to set cue file charcode.
  13. Wav override:
  14. Normally, this program reads audio from file which specified by cue.
  15. You can override this filename.
  16. Format:
  17. Output filename format.
  18. If not spicified, use "+%n-%02t.ogg"
  19. %[0-9]*n: Track number
  20. %t : Track name
  21. %p : Track performer
  22. %T : Album name
  23. %P : Album performer
  24. FFmpeg options:
  25. Pass these options to FFmpeg as output file options.
  26. If not specified, use "-c:a libopus -b:a 64k -vn -sn"
  27. EOT
  28. ;
  29. exit(shift|0);
  30. }
  31. my $cuename;
  32. my $cueenc = "";
  33. my $wavor;
  34. my $fnpat;
  35. my @encops;
  36. for(@ARGV){
  37. if(/^(?:-h|--help|-help|-\?)$/){
  38. usage(0);
  39. }elsif(/^-/ .. 0){
  40. push(@encops, $_);
  41. }elsif(!defined($fnpat) && /^\+/){
  42. $fnpat = substr($_, 1);
  43. }elsif(!length($cueenc) && /^:/){
  44. $cueenc = $_;
  45. }elsif(!defined($cuename)){
  46. $cuename = $_;
  47. }elsif(!defined($wavor)){
  48. $wavor = $_;
  49. }else{
  50. usage(1);
  51. }
  52. }
  53. if(!defined($fnpat)){
  54. $fnpat = "%n-%02t.ogg";
  55. }
  56. if(!@encops){
  57. @encops = qw(-c:a libopus -b:a 64k -vn -sn);
  58. }
  59. shift(@encops) if(@encops && $encops[0] eq "-");
  60. if(!defined($cuename)){
  61. usage(1);
  62. }
  63. my @tracks;
  64. my $disc = {};
  65. my $pt = $disc;
  66. my $cue;
  67. open($cue, "<$cueenc", $cuename) || die "cue open error";
  68. while(<$cue>){
  69. my @lt;
  70. while(/(?|([^\s"]+)|"((?:[^"]|(?<=(?<!\\)\\)")*)")/g){
  71. push(@lt, $1);
  72. $lt[$#lt] =~ s/\\([\\"])/$1/g;
  73. }
  74. if($lt[0] eq "PERFORMER" || $lt[0] eq "TITLE"){
  75. $pt->{lc($lt[0])} = $lt[1];
  76. }elsif($lt[0] eq "FILE"){
  77. $wavor = $lt[1] if(!defined($wavor));
  78. }elsif($lt[0] eq "INDEX"){
  79. if($lt[2] !~ /^([0-9]{2}):([0-9]{2}):([0-9]{2})$/){
  80. die "index error";
  81. }
  82. my $s = $1 * 60 + $2 + $3 / 75;
  83. if($lt[1] == 0){
  84. $pt->{prgap} = $s;
  85. }elsif($lt[1] == 1){
  86. $pt->{start} = $s;
  87. $pt->{prgap} = $s if(!defined($pt->{prgap}));
  88. }
  89. }elsif($lt[0] eq "TRACK"){
  90. if($tracks[$lt[1]]){
  91. die "track has same number";
  92. }
  93. $pt = {num => +$lt[1]};
  94. $tracks[$lt[1] - 1] = $pt;
  95. }
  96. }
  97. if(!defined($wavor)){
  98. die "give audio file";
  99. }
  100. for(0 .. $#tracks){
  101. my $track = $tracks[$_];
  102. if(!$track){
  103. next;
  104. }
  105. my @lo;
  106. @lo = ("-t", $tracks[$_+1]{prgap} - $track->{start}) if($tracks[$_+1]);
  107. my %ma = (
  108. track => $track->{num},
  109. title => $track->{title},
  110. artist => $track->{performer},
  111. album => $disc->{title},
  112. album_artist => $disc->{performer}
  113. );
  114. my @metaops;
  115. while(my ($k, $v) = each(%ma)){
  116. push(@metaops, "-metadata", "$k=$v") if(defined($v));
  117. }
  118. my %fa = (
  119. n => $track->{num},
  120. t => $track->{title},
  121. p => $track->{performer},
  122. T => $disc->{title},
  123. P => $disc->{performer}
  124. );
  125. my $fh = sub{
  126. my $l = shift || 0;
  127. my $n = shift;
  128. my $p = ($l =~ /^0/) ? "0" : " ";
  129. my $r = defined($fa{$n}) ? $fa{$n} : "";
  130. my $a = $l - length($r);
  131. $a = 0 if($a < 0);
  132. return ($p x $a) . $r;
  133. };
  134. my $fname = $fnpat;
  135. $fname =~ s/%([0-9]*)([ntpTP])/$fh->($1, $2)/ge;
  136. system("ffmpeg", "-ss", $track->{start},
  137. "-i", $wavor, @metaops, @encops, @lo, $fname);
  138. }
ダウンロード 印刷用表示

このコピペの URL

JavaScript での埋め込み

iframe での埋め込み

元のテキスト