名取さなの #どくラジ 録音切り出しPowerShell

みなさん、どくラジは~ #どくラジ 聞いてますか?(?)
表題の通り、録音ファイルの切り出しをPowerShellで自動化した話です。ネタがなくてね。。。

録音機材:Panasonic SC-HC320
受信環境:東京都府中市 文化放送 FMワイド 91.6 MHz
録音時間:1:57~3:05
録音先:USBメモリ

上記機材ですが、録音周りが主機能ではないためかなり機能的に弱いです。なので、全くおすすめはしません。。(曜日指定できないのが致命的。)薄くてサイズ的には便利なんですけどね。

少し長い時間録音して、確実にどくラジが録音されるようにしてあります。ちなみにスタート時間がギリギリなのは、放送開始が早まることは比較的少ないかな・・・という考え。

最初はAudacityを用いて手動編集していたのですが、流石に毎週これをやる時間はなく・・・ マクロを組んだりと半自動化に取り組みましたが、どうせならファイルコピーと話数リネーム以外は全自動化したい!という考えが生まれてしまいAudacityを卒業しました

SDRサーバ等を構築して全自動で録音、というのも考えたのですが・・・そこまで来るともうRadikoでいいのでは、となり。
ラジオ然としているのは結構大事だと個人的には思います。今回の場合はラジオ聴き器(ラジカセ)から手動でファイルをコピーする、そんな†温かみ†ですね。(訳:SDRサーバ構築や機材面が面倒)

メインのコードは以下の通り。(_RUN.batは、以下を叩くだけなので省略。)
pipでeyeD3を入れておく必要有りです。この辺を参考に、どうぞ。
https://eyed3.readthedocs.io/en/latest/installation.html

$ErrorActionPreference = "Stop"

#放送曜日が変わった場合、適宜startdateを変更
$startdate = "2023/7/7"

#放送が延期やスキップされた場合、日付の計算に影響があるためskippedを加減算する
$skipped = 0

#タグ文字列
$title = "名取さなの毒にも薬にもならないラジオ"
$artist = "文化放送 - 名取さな"

#切り出し時間 入力ファイル切り出し開始時間と、出力ファイル長さ
$instart = 205
$outlen = 1835

#他定数
$workdirname = "C:\Audacity\DokuRadi\ffmpeg"
$outdirname = "C:\Audacity\DokuRadi\どくラジ編集済"
$rawdirname = "C:\Audacity\DokuRadi\RAW"
$recordedfilename = "TR_0001.MP3"

[void][System.Reflection.Assembly]::Load("Microsoft.VisualBasic, Version=8.0.0.0, Culture=Neutral, PublicKeyToken=b03f5f7f11d50a3a")

Set-Location $workdirname

$ibox1 = [Microsoft.VisualBasic.Interaction]::InputBox("RAWディレクトリへ格納の上、話数を入力(数字のみ)", "どくラジ変換ばっち")

if ([int32]::TryParse($ibox1, [ref]$null) -eq $true) {
    $datecalc = (Get-Date $startdate).AddDays(7 * ($ibox1 - 1 + $skipped)).ToString("yyyy-MM-dd")
    $ofname = "$($outdirname)\$($title)_#$($ibox1)_$($datecalc).mp3"
    $ofnamet = "$($workdirname)\temp.mp3"

    if (Test-Path $ofnamet) {
        Remove-Item -Force $ofnamet
    }

    .\ffmpeg -i "$($rawdirname)\#$($ibox1)\$($recordedfilename)" -ac 2 -ar 44100 -ab 96k -ss $instart -t $outlen -af "afade=t=in:st=$($instart):d=1,afade=t=out:st=$($outlen + $instart - 1):d=1" "$($ofnamet)"

    Move-Item -Force $ofnamet $ofname
    
    eyeD3 --to-v2.4 "$($ofname)"
    eyeD3 --encoding utf8 -a "$($artist)" -A "$($title)" -t "#$($ibox1) $($datecalc)" "$($ofname)"

    Invoke-Item "$($outdirname)"
}
else {
    Write-Host "INPUT ERROR"
}

Workディレクトリ等がC:\Audacity\配下でカオスですが、これは僕が部屋を片付けられない人間なので、大変に致し方ないことなのです。

運用ですが以下の通りです。

  1. USBメモリ録音
  2. ある程度溜まったら、PCへ接続
  3. ラジカセの仕様で1hごとにファイル分割が行われるため、アルバムディレクトリごと「RAW」ディレクトリへ投入
  4. どくラジは一週間ごとなので、6個飛ばしでディレクトリを残す
  5. アルバムディレクトリの名前を「#<話数>」に変更
  6. _RUN.batを起動し、話数を入力すると自動的にRAWディレクトリから該当ファイルを読み込み、切り出しを実行する

意外と手動ですね。これが†温かみ†です。

皆さんも工夫(?)で良い #どくラジ 生活を!

追記2023/12/22

入力をなくした(最初からこうすりゃ良かったのやつ)


$ErrorActionPreference = "Stop"

#放送曜日が変わった場合、適宜startdateを変更
$startdate = "2023/7/7"

#放送が延期やスキップされた場合、日付の計算に影響があるためskippedを加減算する
$skipped = 0

#タグ文字列
$title = "名取さなの毒にも薬にもならないラジオ"
$artist = "文化放送 - 名取さな"

#切り出し時間 入力ファイル切り出し開始時間と、出力ファイル長さ
$instart = 205
$outlen = 1835

#他定数
$workdirname = "C:\Audacity\DokuRadi\ffmpeg"
$outdirname = "C:\Audacity\DokuRadi\どくラジ編集済"
$rawdirname = "C:\Audacity\DokuRadi\RAW"
$recordedfilename = "TR_0001.MP3"

Set-Location $workdirname

$ibox1 = (Get-ChildItem $outdirname -File).Count + 1

if ([int32]::TryParse($ibox1, [ref]$null) -eq $true) {
    for ($loopmax = (Get-ChildItem $rawdirname -Directory).Count; $ibox1 -le $loopmax; $ibox1++) {
        $datecalc = (Get-Date $startdate).AddDays(7 * ($ibox1 - 1 + $skipped)).ToString("yyyy-MM-dd")
        $ofname = "$($outdirname)\$($title)_#$($ibox1)_$($datecalc).mp3"
        $ofnamet = "$($workdirname)\temp.mp3"
    
        if (Test-Path $ofnamet) {
            Remove-Item -Force $ofnamet
        }
    
        .\ffmpeg -i "$($rawdirname)\#$($ibox1)\$($recordedfilename)" -ac 2 -ar 44100 -ab 96k -ss $instart -t $outlen -af "afade=t=in:st=$($instart):d=1,afade=t=out:st=$($outlen + $instart - 1):d=1" "$($ofnamet)"
    
        Move-Item -Force $ofnamet $ofname
        
        eyeD3 --to-v2.4 "$($ofname)"
        eyeD3 --encoding utf8 -a "$($artist)" -A "$($title)" -t "#$($ibox1) $($datecalc)" -n $ibox1 "$($ofname)"    
    }
    
    Invoke-Item "$($outdirname)"
}
else {
    Write-Host "INPUT ERROR"
}