From: satomichan Date: Sun, 5 Oct 2025 11:06:45 +0000 (+0900) Subject: ffmpeg にオプション loglevel, seg_max_retry を渡せるようにした. ログ出力モードを追加. X-Git-Url: https://satomichan.jp/gitweb/?a=commitdiff_plain;ds=sidebyside;p=rec-radiko.git ffmpeg にオプション loglevel, seg_max_retry を渡せるようにした. ログ出力モードを追加. --- diff --git a/radiru2-dl.pl b/radiru2-dl.pl index ed5480d..9bee35c 100755 --- a/radiru2-dl.pl +++ b/radiru2-dl.pl @@ -41,9 +41,6 @@ use Encode; use XML::XPath; #sudo apt install libxml-xpath-perl use XML::XPath::XMLParser; use Getopt::Long qw(:config posix_default no_ignore_case gnu_compat); -#use Time::Piece; -use IPC::Open3 qw(open3); -use Symbol qw(gensym); sub dp; my $config_url = 'https://www.nhk.or.jp/radio/config/config_web.xml'; @@ -51,14 +48,19 @@ my $config_url = 'https://www.nhk.or.jp/radio/config/config_web.xml'; # オプション解析 -my $is_check_mode = 0; -my $is_verbose_mode = 0; -my $retry = 5; -GetOptions('check|c' => \$is_check_mode, - 'verbose|v' => \$is_verbose_mode, - 'retry|r=i' => \$retry, +my $is_check_mode = 0; +my $is_verbose_mode = 0; +my $ffmpeg_loglevel = 'fatal'; #ログレベル fatal: 致命的なもののみ出力 +my $ffmpeg_seg_max_retry = 5; #hls エラー発生時にセグメントを再読み込みする最大回数 +my $retry = 5; +GetOptions('check|c' => \$is_check_mode, + 'verbose|v' => \$is_verbose_mode, + 'ffmpeg-loglevel=s' => \$ffmpeg_loglevel, + 'ffmpeg-seg_max_retry=i' => \$ffmpeg_seg_max_retry, + 'retry|r=i' => \$retry, ); my($station, $req_duration, $output) = @ARGV; +$output = Encode::decode('UTF-8', $output); #HLS URL 取得 $station = 'tokyo-r2' if $station eq 'r2'; @@ -85,10 +87,15 @@ for(my $try = 0; $try <= $retry; $try++){ dp "try: $try numbered_filename: $numbered_filename this_duration: $this_duration"; - $ret = system('ffmpeg', '-fflags', '+discardcorrupt', #破損したフレームを破棄 - '-loglevel', 'fatal', #ログレベル 致命的なもののみ出力 - '-y', #Overwrite -> Yes - '-i', $hls_url, '-t', $this_duration, $numbered_filename); + my $ffmpeg = 'ffmpeg -fflags +discardcorrupt '. #破損したフレームを破棄 + "-loglevel $ffmpeg_loglevel ". + "-seg_max_retry $ffmpeg_seg_max_retry ". #hls エラー発生時にセグメントを再読み込みする最大回数 + '-y '. #Overwrite -> Yes + "-i $hls_url ". + "-t $this_duration ". + "'$numbered_filename' "; + print Encode::decode('UTF-8', `$ffmpeg 2>&1`); + $ret = $? >> 8; #出力ファイルが存在する? next unless -f $numbered_filename; @@ -130,10 +137,7 @@ sub get_hls_url { #ffmpeg で録音時間を取得 (秒数で返す) sub get_rec_duration_by_file { my($file) = @_; - my $err = gensym; - my $pid = open3(undef, undef, $err, "ffmpeg -i $file"); - my $info = do { local $/; <$err> }; - waitpid($pid, 0); + my $info = do { local $/; `ffmpeg -i '$file' 2>&1` }; if ($info =~ /Duration: (\d+:\d{2}:\d{2})\./) { return duration2sec($1); diff --git a/rec-nhk-radio.pl b/rec-nhk-radio.pl index 84190f8..53fd5eb 100755 --- a/rec-nhk-radio.pl +++ b/rec-nhk-radio.pl @@ -58,14 +58,20 @@ die "保存先 $DIR_SAVE_TO に書き込み権限がありません." # オプション解析 -my $is_check_mode = 0; -my $is_verbose_mode = 0; -my $offset_time_sec = 35; #開始オフセット(秒) -my $end_margin_sec = 30; #後方余白(秒) -GetOptions('check|c' => \$is_check_mode, - 'verbose' => \$is_verbose_mode, - 'offset-time=i' => \$offset_time_sec, - 'end-margin=i' => \$end_margin_sec ); +my $is_check_mode = 0; +my $is_verbose_mode = 0; +my $is_logging_mode = 0; +my $ffmpeg_loglevel = ''; +my $ffmpeg_seg_max_retry = ''; +my $offset_time_sec = 30; #開始オフセット(秒) +my $end_margin_sec = 40; #後方余白(秒) +GetOptions('check|c' => \$is_check_mode, + 'verbose' => \$is_verbose_mode, + 'logging' => \$is_logging_mode, + 'ffmpeg-loglevel=s' => \$ffmpeg_loglevel, + 'ffmpeg-seg_max_retry=s' => \$ffmpeg_seg_max_retry, + 'offset-time=i' => \$offset_time_sec, + 'end-margin=i' => \$end_margin_sec ); @@ -74,6 +80,9 @@ unless (@ARGV) { my $script_name = basename($0, ''); my $usage = << " EOM_USAGE"; USAGE) $script_name [ -c | --check | --verbose ] + [--logging] + [--ffmpeg-loglevel ] + [--ffmpeg-seg_max_retry ] [--offset-time <開始オフセット(秒)>] [--end-margin <後方余白(秒)>] <放送局ID> <録音開始日> <録音開始時刻> [<録音長さ(分)> <タイトル>] @@ -85,6 +94,12 @@ unless (@ARGV) { --verbose を指定すると, job発行コマンドと番組表の内容を表示してからjob発行をする, 冗長表示モード になります. + ffmpeg の loglevel を info(ffmpegのデフォルト) や warning, quiet 等から指定します. + このコマンドにおけるデフォルトは fatal: 致命的なもののみ出力 です. + + hls エラー発生時にセグメントを再読み込みする最大回数を指定します. + デフォルトは 5回 です. + <開始オフセット(秒)> には, 録音開始時刻の00秒から実際に録音を開始するまでの秒数を指定します. デフォルトは $offset_time_sec 秒です. @@ -138,13 +153,20 @@ die "無効な引数です." unless ($y && $m && $d && $time_h <= 24 && $time_h my $file_name_base = sprintf('%04d-%02d-%02d_%02d%02d_nhk-%s_%s_%dmin', $y, $m, $d, $time_h, $time_m, $station, $title, $min); my $mp3 = "${file_name_base}.mp3"; +my $txt = "${file_name_base}.txt"; my $duration = get_duration_string($min, $end_margin_sec); # コマンド構築 -my $rec_cmd = "cd $ENV{RADIKO_SAVE_TO}; $SLEEP $offset_time_sec; $DL $station $duration $mp3; $CHMOD $FILE_PERMISSION $file_name_base*.mp3; "; +my $rec_cmd = "cd $ENV{RADIKO_SAVE_TO}; $SLEEP $offset_time_sec; ". + "$DL ". + (length $ffmpeg_loglevel ? "--ffmpeg-loglevel $ffmpeg_loglevel " : ''). + (length $ffmpeg_seg_max_retry ? "--ffmpeg-seg_max_retry $ffmpeg_seg_max_retry " : ''). + "$station $duration $mp3 ". + ($is_logging_mode ? ">> $txt; " : '; '). + "$CHMOD $FILE_PERMISSION $file_name_base*.mp3; "; my $at_time = sprintf('%d:%02d %02d.%02d.%02d', $time_h, $time_m, $d, $m, ($y - int($y/100)*100 ) ); my $cmd = qq{$ECHO -e '$BASH << EOC\\n$rec_cmd\\nEOC' | $AT "$at_time"};