Blog

  • GPUSORABANさんを使ってみた(3)DeepFilterNet3も試しました。

    本記事は、
    これまでに構築した GPU 対応 PyTorch 環境を前提に、DeepFilterNet3 の GPU 動作検証と動画音声のノイズ除去テストを行った記録 です。

    前回の確認で、DenoiserがGPUを使用して動作する環境構築と実際にノイズ除去を試すところまで行いました。ffmpegでモノラルに変換した効果もあってか、Denoiserでのノイズ除去と音量ダイナミクスの安定化にはそれなりに効果があることが分かりました。(本当は解析して数値で記載するほうが分かり易いのですが、現状は私の個人的な感想です。)

    ところで補正後の音声にもまだマイクに何かがぶつかるような音がありました。
    自動でどこまでできるか、も確認したいので、衝撃音に強いらしいDeepFilterNetを試すことにしました。

    記事内のディレクトリの位置や名前、ファイル名などは私が自分で利用しやすいように変更したりしていますので、試される場合はご自身の環境に合わせて読み替えてください。

    1.DeepFilterNet3インストール

    今回も前回の仮想環境を利用します。

    $ conda activate denoiserenv

    ・deepfilternet 本体をインストール

    $ pip install deepfilternet

    ・pyファイル格納用にディレクトリを作成しました。

    $ mkdir ~/scripts

    $ cd ~/scripts

    ・コードを書いて.pyファイルに保存(ここではファイル名をtest_dfn3.pyにしました。)

    import torch
    from df.enhance import enhance, init_df, load_audio, save_audio
    import os
    
    # 入力ファイル(今回使いたいファイル)
    INPUT_WAV = os.path.expanduser(
        "~/denoiser_test/denoised_wavs/lecture_raw_enhanced.wav"
    )
    
    # 出力ファイル(DFN3通した結果)
    OUTPUT_WAV = os.path.expanduser(
        "~/denoiser_test/denoised_wavs/lecture_raw_enhanced_dfn3.wav"
    )
    
    # 1チャンクの長さ(秒)
    CHUNK_SECONDS = 600  # 10分。心配なら 300(5分) にしてもOK
    
    
    def main():
        print("PyTorch version:", torch.__version__)
        print("CUDA available:", torch.cuda.is_available())
    
        # DeepFilterNet 初期化(標準で DeepFilterNet3)
        model, df_state, _ = init_df()
        print("Model sample rate:", df_state.sr())
        print("Model device before .to():", next(model.parameters()).device)
    
        # GPUへ
        if torch.cuda.is_available():
            model = model.to("cuda")
            print("Model device after .to():", next(model.parameters()).device)
        else:
            print("CUDA not available → CPU動作になります")
    
        # 音声読み込み(モデルのサンプリングレートに合わせてロード)
        print("Loading:", INPUT_WAV)
        audio, sr = load_audio(INPUT_WAV, sr=df_state.sr())
        # audio: [channels, samples]
        print("Input sr:", sr, "Shape:", audio.shape)
    
        # モノラル前提なので 1ch にして扱う
        audio = audio.squeeze(0)  # [samples]
        total_samples = audio.shape[0]
        chunk_samples = CHUNK_SECONDS * df_state.sr()
    
        print(f"Total samples: {total_samples}")
        print(f"Chunk samples: {chunk_samples} ({CHUNK_SECONDS} sec)")
    
        enhanced_chunks = []
    
        start = 0
        chunk_idx = 0
    
        with torch.no_grad():
            while start < total_samples:
                end = min(start + chunk_samples, total_samples)
                chunk_idx += 1
                print(f"Processing chunk {chunk_idx}: samples {start} - {end}")
    
                # [1, chunk_len] の形に戻す
                chunk = audio[start:end].unsqueeze(0)
    
                # DFN3 でノイズ除去
                enhanced_chunk = enhance(model, df_state, chunk)
    
                # CPU側に集めておく
                enhanced_chunk = enhanced_chunk.squeeze(0).cpu()
                enhanced_chunks.append(enhanced_chunk)
    
                start = end
    
        # チャンクを結合
        enhanced_full = torch.cat(enhanced_chunks, dim=-1)
        print("Enhanced total samples:", enhanced_full.shape[-1])
    
        # 保存
        save_audio(OUTPUT_WAV, enhanced_full, df_state.sr())
        print("Saved:", OUTPUT_WAV)
    
    
    if __name__ == "__main__":
        main()

    実行します。

    $ python test_dfn3.py

    私の環境ではこれで無事動作しました。
    効果があったか、というと今回は”微妙”と言わざるを得ない結果でした。
    ただ、悪くなった部分は見受けられなかったので、
    いったん以下のようなフローにしようと思います。

    mp4 → ffmpegで音声抽出(WAV)

    ステレオ → モノラル(整える)

    DFN3(衝撃音・接触音・瞬間ノイズ対策)

    Denoiser(背景ノイズ・ブレス音を軽減、明瞭度UP)

    ffmpegで動画と合成

    次回はこのフローで明瞭な咳払い入りの音声がどれくらい補正されるかを試してみます。

  • GPUSOROBANさんを使ってみた(2)Denoiser環境構築

    本記事は、
    前回構築した GPU 対応 PyTorch 環境を前提に、Denoiser の GPU 動作検証と動画音声のノイズ除去テストを行った記録 です。

    動画を撮るのもスマホのカメラの機能を利用する程度で、撮った動画もインスタグラムのストーリーズへそのまま上げるくらいしかしていなかった素人な私ですが、
    「最近はAIでノイズ除去とか簡単にできなるんじゃないですかね?」
    と相談をいただきました。
    世の中簡単なものって無いですよ…とも言えず、乾いた笑いで答えておいたのですが、最近興味のある分野でもあるので試してみることにしました。

    Facebook(Meta / FAIR)がGitHubに公開しているDenoiserですが、少し時間の経った技術のようです。(2020年頃?)
    生成AIに相談したら候補に挙がったので、とくに深く考えずに選択してみましたが、前回書いたような環境ですので、結果良かったようです。
    Hybrid DemucsやAudiocraftについても、今回の環境でGPUを使用して動作するかの確認もいずれしてみようと思いますが、まずは”AIを使ってノイズ除去”が出来るか、その際にGPUを使用できるか、Denoiser(AI)を使って確認することにします。

    1.今回のサンプル動画の課題

     ・ブレスノイズが激しい
     ・音声の左右のバランスが悪い

    今回入手したサンプル動画の音声はこの2点を何とかしたい、というものでした。
    テスト的に実施するものなので、このうち「音声の左右のバランスが悪い」は単純にステレオをモノラルにして解決することに。
    あくまで呼吸音を含めたノイズ低減と話者の声の明瞭度アップ、安定化を目標にすることしました。

    2.やりたいことの流れと担当部分

    動画ファイルから音声取り出し(ffmpeg)

    ステレオからモノラルに変換(ffmpeg)

    ノイズ低減(Denoiser)

    声の明瞭度や音量ダイナミクスの安定化(Denoiser)

    ノイズ除去後の音声を動画へ再結合(ffmpeg)

    AAC へのエンコード(音声を動画用フォーマットへ)(ffmpeg)

    Denoiser部分がAIとGPU利用部分、ffmpeg部分は実行時の設定値で調整で使うのはCPUです。

    3.環境構築

    Pytorch、CUDAをインストールしてGPUを認識するところまでは前回の記事を参照ください。

    ・ffmpegインストール

    $ sudo apt update
    $ sudo apt install -y ffmpeg

    必要な音声フィルタが入っているか確認します。

    #ノイズ関連
    $ ffmpeg -filters | grep -E ‘afftdn|anlmdn’

    #イコライザ・帯域系
    $ ffmpeg -filters | grep -E ‘equalizer|anequalizer|highpass|lowpass’

    #ラウドネス正規化
    ffmpeg -filters | grep loudnorm

    ここで

    afftdn
    anlmdn
    equalizer
    highpass
    lowpass
    loudnorm

    あたりが表示されていれば大丈夫なようです。

    ・Denoiserインストール

    condaの仮想環境に入っていない場合は入ります。

    $ conda activate denoiserenv

    $ cd ~
    $ mkdir -p denoiser_test
    $ cd denoiser_test

    $ git clone https://github.com/facebookresearch/denoiser.git
    $ cd denoiser

    #依存関係インストール
    $ pip install -r requirements.txt
    $ pip install -e .

    Denoiser が GPU を使ってくれるかテスト

    $ python
    
    >>>import torch
    from denoiser import pretrained
    
    print("torch.cuda.is_available():", torch.cuda.is_available())
    
    model = pretrained.dns64()
    print("loaded model device:", next(model.parameters()).device)
    
    if torch.cuda.is_available():
     model = model.to("cuda")
     print("after .to('cuda'):", next(model.parameters()).device)
    else:
     print("CUDA not available, staying on CPU.")

    ここで

    torch.cuda.is_available(): True

    after .to(‘cuda’): cuda:0

    と出れば、モデルを GPU に載せる準備が完了です。

    フォルダ構成を以下のようにしました。

    ~/denoiser_test
    |-denoised_wavs/
    |-noisy_wavs/
    |-work/

    4.実際に動かしてみる

    ~/denoiser_test/noisy_wavs へmp4ファイルを格納してください。
    私はWinSCPを使用しました。WinSCPでの接続方法もGPUSORBANさんの

    WinSCPでWinodws PCからファイル転送する方法

    で詳しく説明されています。

    ・mp4 から音声だけ抜き出し(wav)

    今回使用したmp4ファイルのファイル名:lecture.mp4

    $ cd ~/denoiser_test/noisy_wavs
    
    $ ffmpeg -i lecture.mp4 \
    -vn -acodec pcm_s16le -ar 48000 -ac 2 \
    work/lecture_raw.wav

    -vn … ビデオ無効
    pcm_s16le … 無圧縮(処理しやすい)
    -ar 48000 / -ac 2 … 48kHz / ステレオに統一

    ・ステレオをモノラルに変換

    $ cd work
    
    $ ffmpeg -i lecture_raw.wav \
     -af "pan=mono|c0=0.5c0+0.5c1" \
     lecture_raw_mono.wav

    ・ノイズ低減処理

    $ cd ~/denoiser_test/denoiser
    
    $ python -m denoiser.enhance \
     --dns48 \
     --device cuda \
     --streaming \
     --batch_size 1 \
     --num_workers 1 \
     --noisy_dir ../noisy_wavs/work \
     --out_dir ../denoised_wavs

    バックスラッシュの次には半角スペースが必要です。スペースなければ動作しなければいいのに、CPUを使って走り出すという…
    別のターミナルを起動して以下のコマンドを実行するとGPUが動作しているか確認できます。

    $ watch -n 1 nvidia-smi

    保存はout_dir(今回だと~/denoiser_test/denoised_wavs)にされます。
    (元のファイル名)_enhanced.wavファイルがそれです。
    同じところに(元のファイル名)_noisy.wavファイルも生成されますが、これは仕様だそうです。
    理由は生成AIに聞いてみてくださいね。

    ・音声を映像に戻す

    戻すというか、動画ファイルをストリーミングして新しい音声と合成する、というイメージですね。

    $ ffmpeg -i ~/denoiser_test/noisy_wavs/lecture.mp4 \
     -i ~/denoiser_test/denoised_wavs/lecture_raw_mono_enhanced.wav \
     -map 0:v -map 1:a \
     -c:v copy \
     -c:a aac -b:a 192k \
     ~/denoiser_test/lecture_denoised.mp4

    今回のテストはここまでです。
    出来上がったファイルの音声は少しは聞きやすくなった気がします。
    ノイズが大きかったところを補正している部分で別のノイズが発生しているのはノイズ補正のせいかもしれませんね。もう一度このフローを流したらどうなるのかな?

    さて次はHybrid Demucsが動作する環境構築ができるかを試すか、教師データを大量に用意して別のシステムを作るか…どうしましょうね笑

  • GPUSOROBANさんを使ってみた(1)

    この記事では、
    GPUSOROBAN で GPU が使える PyTorch 環境を最短で構築するまでの実践ログ
    を書いています。

    知り合いがYoutubeに投稿していたり、自分でもやってみたいかな、と思うこともあって、例えば映り込んだ人の顔にモザイク入れたりとか、すでにAIを利用したサービスやアプリなんかもきっとあるはずなのですが、ある程度カスタマイズしたり、いろいろ試したりもしたいじゃないですか。

    自分の手元の環境は使えそうなGPU環境がない、ということで、一番安価なプランだと従量制で時間50円というGPUSORABANさんを利用することにしてみました。

    いつでも止められるので仕様やら何やらはほぼ調べず…笑<アホや

    最初dockerを使えるプランを選んだのです。なんだか響きだけで<やっぱりアホ
    で、適当に試していたのですが肝心のGPUが使えない…
    無論dockerだからというワケではありません。私がダメな奴だったというだけで。

    ただその時は原因の切り分けも少ししたくて、s16-1-a-standard-ubs22-i というタイプを選び直しました。スペック・プリインストール情報はこちらを参照ください。

    1.まず何にハマったか(TorchとCUDAのバージョン問題)
    プログラマーでもないので(言い訳)インストールはpipだろぅ、となんでもpipでインストールしていたわけですが、関連モジュールにtorch関連があると、勝手にバージョンアップしてしまうワケです。
    で、バージョンアップしないようにインストール進めて、必要なモジュールを1個ずつずつインストールしていったワケですが…torchのバージョンがアプリが要求するバージョンより古い、とかでGPUを使えない、アプリのバージョンを落としても不足があって使えない、といった感じでやはりGPUを使えない時間が過ぎていき…。
    GPUSORABANさんの記事を読み返しました。

    ゼロから分かる!PyTorchのGPU設定と実践レシピ

    ”利用しようとしているPyTorchのバージョンが、どのバージョンのCUDAに対応しているかを事前に確認します。”

    ま、まあ、そうですよね。普通のことですよね汗
    ということでOSとバージョンに合わせたコマンドの記載がある公式ページから環境にあったコマンドを探して実行してみました。

    2.で、実際なにやったか

    ・GPUSORABANさんのインスタンス作成方法はおそらく勘でも出来るはず…

    ・Miniconda のインストール
    あれ、wgetもインストールしたかも…

    $ wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh
    $ bash Miniconda3-latest-Linux-x86_64.sh

    ・GPU を検証するための環境を作る
    condaで仮想?環境みたいなものを作って他に影響を与えないように。
    (Denoiserを試したかったので名前はdenoiserenvにしてみました。)

    で、そのまま勢いでcondaを使用しようとすると怒られるので認証?コマンドを

    $ conda tos accept –override-channels –channel https://repo.anaconda.com/pkgs/main
    $ conda tos accept –override-channels –channel https://repo.anaconda.com/pkgs/r

    ・仮想環境の作成と仮想環境内へ入る

    $ conda create -n denoiserenv python=3.10 -y
    $ conda activate denoiserenv

    pythonも古めなのは前段に書いた色々失敗した結果です笑

    ・PyTorch + CUDA 11.7 のインストール
    公式に記載があったものをそのまま実行しました。

    $ conda install pytorch==2.0.1 torchvision==0.15.2 torchaudio==2.0.2 pytorch-cuda=11.7 -c pytorch -c nvidia

    正直このインスタンスではこれ一択なのでは…いや、結果私にはこれ一択ということで。

    ・MKLの依存回避
    こちらも理由を聞かれても困るのですが、RVCだかの環境構築を試していた時に必要で、その他のアプリ導入時も必要だったので、私の環境では必須なのかも。

    $ conda install "mkl<2024.1" "intel-openmp<2024.1"

    ・動作確認

    python - << 'EOF'
    import torch
    
    print("Torch version :", torch.__version__)
    print("CUDA runtime  :", torch.version.cuda)
    print("CUDA available:", torch.cuda.is_available())
    if torch.cuda.is_available():
        print("GPU:", torch.cuda.get_device_name(0))
    EOF

    で、
    CUDA available: True
    とか
    GPU: NVIDIA RTX A4000
    が表示されて入れば大丈夫、なはず。

    共通の環境構築はここまで。仮想環境の入れ物の名前(ここではdenoiserenv)を変えてやればこの流れで環境構築OKです。

    ”OKです”とか書くとプロの皆さんには鼻で笑われそうですが。。。最終的には
    「Miniconda + PyTorch 2.0.1 + CUDA 11.7 を公式手順で入れる」
    これだけで GPU が安定して使えるようになりました。

    Denoiserの設定や試したことなどは次の機会に。