kazeno memo

メモとか

VOICEVOX CORE 0.15.5 を Google Colab で使ってみる

Google Colab上で、VOICEVOX CORE 0.15.x系を用いて合成音声を生成してみます。

ハマった点

  • Google ColabランタイムのPythonバージョン(3.10)が、VOICEVOXの要求バージョン(3.11)より低い
  • 依存関係を pip install しようとすると、Colabランタイムの再起動を要求され詰む
    • venvの仮想環境内で実行させ解決
  • VOICEVOX COREが外部ライブラリを読み込む際、存在するファイルが読み込めない旨のエラーが発生
    • 外部ライブラリが存在するディレクトリを、LD_LIBRARY_PATHに追加することで解決

環境

  • Python 3.11
  • VOICEVOX CORE 0.15.5

VOICEVOXをGPU (CUDA)で実行する場合、Google ColabのランタイムをT4 GPUに変更してください。

Pythonの環境構築

記事執筆時点で、Google ColabのランタイムはPython 3.10ですが、VOICEVOX CORE 0.15.x系はPython 3.11未満の環境をサポートしていないので動作しません。

Google Colabについて詳しくないのですが、aptでPython3.11をインストールし、venv環境に依存関係をインストール、そしてシェル経由でpythonスクリプトを実行させることで、VOICEVOX CORE 0.15.x系が正常に動作しました。

# Python 3.11 をインストール
!apt update > /dev/null 2>&1
!apt install -y python3.11 python3.11-venv > /dev/null 2>&1

# デフォルトの Python のバージョンを 3.11 に設定
!update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.11 1
!update-alternatives --config python3

# pip と venv(3.11) をインストール
!apt install -y python3-pip > /dev/null 2>&1

次に、venvで仮想環境を作成します。

!python3 -m venv /content/venv

ちなみに、Jupyter Notebookでは、シェルのセッションごとにvenv環境をアクティベートする必要があるようです。

%%bashを用いて、単一のBashセッション内の先頭でアクティベートするか

%%bash
source /content/venv/bin/activate

pip --version # 仮想環境の pip が呼び出される
pip list      # 仮想環境にインストールされたパッケージが表示される

このように、!Bashコマンドを実行するたびにアクティベートする必要があります。

! pip --version # ホスト環境の pip が呼び出される

! source /content/venv/bin/activate; \
  pip --version # 仮想環境の pip が呼び出される

! source /content/venv/bin/activate; \
  pip list # 仮想環境にインストールされたパッケージが表示される

依存関係のインストール

pip

pipで、Wheel形式のVOICEVOXライブラリをインストールします。詳細は、Github のリリースページを参照してください。

# CPU 版(デフォルト)を使用する場合
! source /content/venv/bin/activate; \
  pip install https://github.com/VOICEVOX/voicevox_core/releases/download/0.15.5/voicevox_core-0.15.5+cpu-cp38-abi3-linux_x86_64.whl

# GPU (CUDA) 版を使用する場合
# `nvidia-cuda-runtime-cu11` パッケージも必要
! source /content/venv/bin/activate; \
  pip install nvidia-cuda-runtime-cu11 \
              https://github.com/VOICEVOX/voicevox_core/releases/download/0.15.5/voicevox_core-0.15.5+cuda-cp38-abi3-linux_x86_64.whl

その他

VOICEVOXプロジェクトが用意しているダウンロードスクリプトを用いて、Open JTalkなどの外部ライブラリを取得します。CUDA版を使用する場合は、--deviceオプションにcudaを指定してください。

Open JTalkは、SourceForgeJAISTミラーサーバから取得されますが、Google Colab環境だとダウンロード速度が遅くなってしまいます。 ホスト名を jaist.dl.sourceforge.net から downloads.sourceforge.net に置き換えることで、ダウンロード速度が改善します。

# GPU (CUDA) 版を使用する場合、`--device cpu` を `--device cuda` に修正してください
! source /content/venv/bin/activate; \
  curl -sL https://github.com/VOICEVOX/voicevox_core/releases/download/0.15.5/download.sh \
    | sed 's/jaist\.dl/downloads/g' \
    | bash -s -- --device cpu

ライブラリの読み込み

from voicevox_core import VoicevoxCoreのようにVoicevoxCoreをロードすると、依存ライブラリが存在するにもかかわらず、以下のようなエラーが発生しました。

OSError: libcublas.so.11: cannot open shared object file voicevox

これは、ダウンロードスクリプトで取得した依存ライブラリ(*.so.*ファイル)が見つからないというエラーです。

解決方法は、LD_LIBRARY_PATHに依存ライブラリが存在するパスを追加するだけです。

%env LD_LIBRARY_PATH=/content/voicevox_core/:{os.environ['LD_LIBRARY_PATH']}

読み込みテスト

事前に、/content/voicevox_coreディレクトリに移動しておいてください。

%cd /content/voicevox_core

VOICEVOXのスピーカーIDなどを確認できる、METASを表示するスクリプトを実行してみます。

%%bash
source /content/venv/bin/activate

# スクリプトをヒアドキュメントとして実行
python3 << EOF

from pathlib import Path
from pprint import pprint
from voicevox_core import VoicevoxCore, METAS

# VOICEVOX CORE を読み込んでみる
core = VoicevoxCore(open_jtalk_dict_dir=Path('open_jtalk_dic_utf_8-1.11'))

# METAS 情報を出力してみる
pprint(METAS)

EOF

METAS情報が出力されれば、正常に動作しています。

合成音声を生成

事前に、/content/voicevox_coreディレクトリに移動しておいてください。

%cd /content/voicevox_core

VOICEVOXプロジェクトが用意しているCLIスクリプトを用いて、任意の文字列を読み上げさせてみましょう。

まず、スクリプトをダウンロードしexample-pyo3.py というファイル名で保存します。

!wget --show-progress -qO example-pyo3.py https://github.com/VOICEVOX/voicevox_core/raw/refs/tags/0.15.5/example/pyo3/run.py

そして、(venv環境で)スクリプトを実行します。 --mode オプションは、環境にあわせて CPUGPU を指定してください。

! source /content/venv/bin/activate; \
  python3 example-pyo3.py --mode GPU ./open_jtalk_dic_utf_8-1.11 "ここに、読み上げる文字列を入力してください。" ./output.wav

これで、output.wav というファイル名の合成音声が出力されました。

Freenetは安全なの? 開発者の主張

Freenetの開発者がHacker Newsに書き込んでいました。

FreenetはTorのように匿名性・耐検閲性があるネットワークです。Torと異なる点は完全なP2Pネットワークであるということ。各ピアはファイルの断片を少しずつホストしており、仮に違法なファイルが共有されたとしても、ネットワークに参加しただけでは罪に問われないはずです。

しかし、アメリカではFreenet利用者が訴追される事例があったようです。これは、Freenetの匿名性が破られたということなのでしょうか?

法執行機関によるFreenet利用者への訴訟を巡る話が興味深かったので翻訳します。


Freenetはまだ存在してるけど、Tor経由で使わない限り危険すぎると思う。

私は10年以上Freenetの開発に携わっているので、このレスに書いていることを解説します。

Freenetは今でも開発されていて、今週も新たなリリースが行われたばかりです。

確かにアメリカでの訴訟は存在しますが、これは「危険」というよりは、よく分からない感じです。

Freenetは匿名化されたP2Pネットワークです。接続方法は3種類ありますが、潜在的に危険なのはそのうちの1つだけです。

  1. オープンネット: 不特定多数のランダムなピアと接続する。

  2. ダークネット: 友人など、特定のピアを選んで接続する。

  3. オープンネットとダークネットの混合: (ここではミックスモードと呼ぶことにしましょう)

オープンネットでは、法執行機関の囮ノードと接続されることでトラフィックを分析される恐れがあります。だからといって、何をダウンロードしたのか他のピアがはっきりわかる訳ではありません。

トラフィックが通過するピアの数は常にランダムで、ダウンロードしているのか通過させているのかを他のピアに通知しないため、もっともらしい反証が成り立ちます。

すべてのトラフィックが暗号化されており、受信者のみがそれを復号できます。つまり、トラフィックを監視して違法なJPEGをフィルタリングする、などということは不可能です。

法執行機関が行ったのは、何らかの計算に基づいて違法ファイルをダウンロードした可能性が高いと主張することでした。Freenetのコアチームもこの計算について認識していて、議論されています。

そのうち対処されると思いますが、開発者の議論を見る限り、この計算はかなりアバウトだと言えるでしょう。つまり、違法ファイルのダウンローダーとされた人物が、実際にダウンローダーだったという絶対的な証拠にはなりえません。

Freenetは20万行以上の複雑なコードなので、もしかすると間違っているかもしれませんが、それでもこれは単なる確率論に過ぎません。

Freenetはランダムな参加者のパソコンにコンテンツを暗号化して保存しているので(これがTorに対するメリットであり、Freenetは完全に分散化されてます!)、能動的にダウンロードしたのではなく、たまたま保存されていたユーザーを法執行機関が告発してしまうことは想像できます。

ただし、Freenetをダークネットかミックスモードで使えばそれなりに安全です。攻撃者に支配されていない友人が多ければ多いほど、統計的な攻撃は難しくなります。

さらに、私の知る限りにおいて同様の訴訟は米国でしか起きておらず、同国の法制度には少し欠陥があると思います。

おそらく、アメリカ以外の国でオープンネットを実行していても、Torノードの運営と同じリスクを負うだけでしょう。(暗号化されていて)調べられないトラフィックを転送し、(暗号化されていて)調べられないトラフィックを保存しているわけですから、それの何が違法なんでしょうか?


cgtzczykldpqさんは、この投稿に続き「シビル攻撃」についても言及しています。


オープンネットでは、法執行機関の囮ノードと接続されることでトラフィックを分析される恐れがあります。

これについては、Freenet固有の問題ではないことを明確にする必要があります。

匿名性を確保しようとするネットワークは、ランダムな人と接続することで、いわゆる「シビル攻撃」に悩まされます。

実際の利用者が1,000人ほどのネットワーク上で、攻撃者が例えば100,000台のマシンを実行していると仮定すれば、あるユーザは攻撃者のマシンにしか接続できない可能性が非常に高くなります。

また、匿名化は複数のピア間でトラフィックをリダイレクトすることが必要ですが、すべてのピアが攻撃者のものであればそれは不可能です。

私の理解では、Torはヒューリスティックな手法によってこの問題に対処しています。 たとえば、ネットワーク内の重要なマシンを入念に監視し、それらが実際に異なるエンティティであることを確認しようとしています。ただ、これは単なる推測であって、厳密な数学的セキュリティとは言えません。

Torを本当に安全なものにしたいならば、ダークネットモードを追加する必要があるでしょう。


mirimirさんは、Freenetの匿名性に否定的な投稿が多いHacker Newsユーザです。Freenetについて様々な記事で言及していて、Freenetの問題点について同意できる部分もありました。(IVPNのプライバシーガイドやブログに寄稿している方だそうです。)

ちなみに、シビル攻撃については、Tor上のBitcoinに関するトラフィックを改ざんし、窃取することを目的としていた「BTCMITM20」や、50以上のAS上で900以上のリレーを運営していた「KAX17」と呼ばれる攻撃者が実際に確認されています。

APTでインストール済みパッケージの一覧を日付順でソート

インストール済みパッケージの一覧を生成

$ find /var/lib/dpkg/info -name '*.list' -exec stat -c $'%n\t%y' '{}' \; \
  | sed -e 's,/var/lib/dpkg/info,,' -e 's/,\.list\t,\t,' \
  | sort > ./dpkg.list

パッケージ一覧を昇順でソート

$ sort -t$'\t' -k2 ./dpkg.list | column -t | less -

VoidLinux Repodata

Main

/current/x86_64-repodata
/current/musl/x86_64-musl-repodata
/current/i686-repodata
/current/aarch64/aarch64-repodata
/current/aarch64/aarch64-musl-repodata
/current/armv6l-repodata
/current/musl/armv6l-musl-repodata
/current/armv7l-repodata
/current/musl/armv7l-musl-repodata

Nonfree

/current/nonfree/x86_64-repodata
/current/musl/nonfree/x86_64-musl-repodata
/current/nonfree/i386-repodata
/current/aarch64/nonfree/aarch64-repodata
/current/aarch64/nonfree/aarch64-musl-repodata
/current/nonfree/armv6l-repodata
/current/musl/nonfree/armv6l-musl-repodata
/current/nonfree/armv7l-repodata
/current/musl/nonfree/armv7l-musl-repodata

Multilib (only x86_64 glibc)

/current/multilib/x86_64-repodata
/current/multilib/nonfree/x86_64-repodata

Debug

/current/debug/x86_64-repodata
/current/musl/debug/x86_64-repodata
/current/debug/i686-repodata
/current/aarch64/debug/aarch64-repodata
/current/aarch64/debug/aarch64-musl-repodata
/current/debug/armv6l-repodata
/current/musl/debug/armv6l-musl-repodata
/current/debug/armv7l-repodata
/current/musl/debug/armv7l-musl-repodata

Value-server SSHホワイトリストに任意のIPアドレスを登録したい

バリューサーバーにSSH/FTP接続する際、IPアドレスを事前に登録しておく必要があります。

ブラウザからコントロールパネルにアクセスしなければ登録できないわけですが、実際にはPOSTリクエストを投げているだけなので、cURLでどうにかなります。

curl https://<サーバー番号>.valueserver.jp/cp/admin.cgi \
  -X POST \
  -H 'Cookie: ID=<コンパネID>; PASS=<コンパネPASS>' \
  --data-raw 'id=<コンパネID>&pass=<コンパネPASS>&id=<コンパネID>&pass=<コンパネPASS>&nomenu=1&remote_host=<IPアドレス>&ssh2=SSH%93o%98%5E'

面倒くさいことに、自身のパブリックIPアドレスとリクエストのIPアドレスが異なっていると、不正なリクエストと言われてしまいます。

mpvでyoutube-dlの代わりにyt-dlpを使う

mpvベースのBaka Mplayerというメディアプレイヤーを使っています。

mpvyoutube-dlと組み合わせることができますが、呼び出すyoutube-dlをyt-dlpに置き換えたいわけです。(シンボリックリンク張れば良さそうですが……)

このコミットによると、ytdl_pathyoutube-dlの代替パスを指定できるようです。

具体的には、mpvの設定ファイル(もしくはコマンドラインのオプションに)にscript-opts=ytdl_hook-ytdl_path=<代替パス>を追加するということです。

mpvの設定ファイルは~/.config/mpv/mpv.confにあります。

$ cat ~/.config/mpv/mpv.conf
script-opts=ytdl_hook-ytdl_path=yt-dlp

試しにBaka MplayerTverのURLをCtrl+Vしてみると、問題なく再生することができました。

Librewolf AppImage版 PGP公開鍵の場所

LibreWolf-96.0.3-2.x86_64.AppImage.sigA98C3D1364D8C16408143C2E2954CC8585E27A3Fで署名されています。

これは、Librewolfのコア開発者である@ohfpさんの鍵です。

"ohfp repo key (Repository signing key for privacyshark repo) <1813007-ohfp@users.noreply.gitlab.com>"

GitLabやGitHubの場合、ユーザーページのURL末尾に.gpgを追加することで、PGP公開鍵を入手できます。(同様に、.keysを追加することでSSH公開鍵を入手できます)

GnuPGを使用している場合、--recv-keysオプションを使うことで、公開鍵サーバから対応する鍵を検索し自動でインポートしてくれます。

$ gpg --recv-keys 0xA98C3D1364D8C16408143C2E2954CC8585E27A3F

Rootless modeでlinuxserver.ioコンテナのPUID/PGIDがうまく設定できない?

linuxserver.ioの提供するコンテナは、環境変数PUID(uid) PGID(gid)で実行ユーザーを指定できます。(例えば、PUID/PGID=1000とすれば一般ユーザーで実行できます。)

ただし、DockerをRootless modeで実行している場合、PUID=1000を指定するとホスト側は100999に、PUIDを指定しないと100910といったuid/gidになってしまいます。

これは、ホスト・コンテナ間のuid/gidマッピングが通常のDockerとRootless modeで異なることが原因だと思われます。

Rootless modeでは、ホストのuid 1000がコンテナ内のuid 0として扱われます。1 2

そして、Rootless mode上のlinuxserver.ioコンテナでは、uid/gidがこのようにマッピングされているようです。

PUID ホスト
PUID=指定せず 100910
PUID=1000 100999
PUID=0 1000

つまり、Rootless modeでlinuxserver.ioコンテナのuid/gidに1000を指定したい時は、明示的にPUID/PGID=0を指定する必要があるということです。

動画のリサイズ 垂直・水平解像度 どちらに合わせるのが最適か?

1920x1040の動画ファイルをHD(720p)に縮小する場合、垂直解像度(1040)を720に合わせるのか、水平解像度(1920)を1280に合わせるのが良いのか。

また、ffmpeg--scale=を使いリサイズする場合、サイズを偶数にする必要があるようですが、1920x1040の場合は奇数で、あまりが出ます。これは切り捨てたほうが良いのでしょうか?

1920x1040という解像度は、映画で使用されるビスタビジョン(アメリカンビスタ)というようです。

VLCのフォーラムにトリミングとサイズ変更についてのガイドがありました。ただし、これが正しいのかそうでないか全くわからないです。


  1. まず、元動画のアスペクト比を計算します。

    アスペクト比=水平/垂直なので、1920x1040の場合、1.84615384615=1920/1040となります。

    (Wikipediaによればアメリカンビスタのアスペクト比は「1.85:1」とのことで、上記の計算とほぼ合致します)

  2. 元動画のアスペクト比を計算したら、次に720pの解像度を計算する必要があります。

    720p規格では、水平解像度が最大1280px・垂直解像度が最大720pxと規定されているそうです。これに基づいて次のいずれかの計算が必要です。

    • アスペクト比 > 16:9=1.77(7)の場合(アスペクト比が1.77より高い)

      水平解像度を1280pxに固定します。垂直=1280/アスペクト比という式で垂直解像度を計算します。

    • アスペクト比 > 16:9=1.77(7)の場合(アスペクト比が1.77より低い)

      垂直解像度を720pxに固定します。水平=720*アスペクト比という式で水平解像度を計算します。

    1920x1040の場合、1.77より高いので水平解像度を1280に固定します。垂直解像度は上記の式によって693.333333335=1280/1.84615384615となります。

  3. 垂直解像度が693.333333335の場合、偶数にするため切り上げ(694)、もしくは切り捨て(692)が必要です。この場合「アスペクト比 誤差(AR error)」が低い方を選ぶ必要があります。

    切り上げ・切り捨て両方のアスペクト比を求め、元動画のアスペクト比とより誤差の少ない方が最適な解像度ということです。

    まず、694と692のアスペクト比を計算し、そこから元動画のアスペクト比(1.84615384615)を引きます。

    • 1280/694=1.84438040346 1.84438040346-1.84615384615=-0.00177344269
    • 1280/692=1.84971098266 1.84971098266-1.84615384615= 0.00355713651

    最適な垂直解像度は694であることがわかりました。


1.33:1 - 1436x1080 or 1440x1080? 1.37:1 - 1480x1080 or 1484x1080? 1.66:1 - 1788x1080 or 1792x1080 or 1796x1080 or 1800x1080? 1.85:1 - 1920x1036 or 1920x1040? 2.35:1 - 1920x816? 2.55:1 - 1920x752? 2.39:1 - 1920x800?