0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Python: RealMediaをwavに変換するスクリプト

Last updated at Posted at 2024-02-12

世の中的に需要はないかと思いますが、 すぐ忘れる未来の自分用のメモです...

さるところからRealMedia(え?今どき?)で構築された音声データベース(何じゃそりゃ?)からデータを取り出してほしい、すぐ欲しい、という依頼があり、その時は件数も少なかったので

  1. htmlのソースからsmilファイルの場所を探す
  2. smilファイルをエディターで開いて
  3. .rmファイルの場所、start/end timeを特定して
  4. VLCでwavに変換し
    • さすがにここはバッチ処理しました。
    • でもいらなかった。
    • rmはAudacityで直接ひらけました...
  5. Audacityでstart/end timeでトリムしてwavでエクスポート(ここは手動...)

というようなことを延々としました。

これって自動化できるよね?ということで、smilファイルと同階層に置いて、同名のwavを作って、outputというフォルダに入れてくれるスクリプトを考えてみました。

import xml.etree.ElementTree as ET
import subprocess
from datetime import timedelta

# smilから rmのパスの文字列、 開始(秒:float)、 終了(秒:float)のタプル に
rm_info = lambda smil_file : (
    (audio_attrib :=
        ET.parse(smil_file)
        .getroot()
        .find("body")
        .find("par")
        .find("audio")
        .get
    )("src")
    .replace("\\","/")      # セパレーターのバックスラッシュをスラッシュに変換

    , (seconds_from_attrib := lambda attrib_str :
            time_in_seconds(
                audio_attrib(attrib_str)[4:]    # 文字列先頭の"nts="を除去
            )
        )("clip-begin")

    , seconds_from_attrib("clip-end")
)

# hh:mm:ss.ss/mm:ss.ss/ss.ss形式から 秒:float に
time_in_seconds = lambda time_str : timedelta(
    0       # days
    , (times_split_reversed := [
            float(x)
            for x
            in time_str
                .split(":")
                [::-1]
            ]
        )[0]  # seconds
    , 0     # milliseconds
    , 0     # microseconds
    , *times_split_reversed[1:]   # minutes, hours (optional)
    ).total_seconds()

def convert_to_wav(rm_file, start_time, end_time, output_file):
    subprocess.run(
        [
            "/opt/homebrew/bin/ffmpeg",
            "-ss",
            str(start_time),
            "-t",
            str(end_time - start_time),
            "-i",
            rm_file,
            "-acodec",
            "pcm_s16le",
            "-ar",
            "44100",
            output_file,
        ]
    )


if __name__ == "__main__":
    import glob
    import os

    out_path = "../output/"
    os.makedirs(out_path, exist_ok=True)

    for smil_file in glob.glob("*.smi") :

        convert_to_wav(
            *rm_info(smil_file)
            , f"{out_path}{os.path.splitext( os.path.basename( smil_file))[0]}.wav"
        )

ffmpegの位置は自分の環境での決め打ちになってます。
エラー処理はしてません。

とりあえず目的は果せたのでここに残しておきます。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?