コンテンツにスキップ

Recent Posts

LivePortrait デモの手順(Mac版)


概要

この記事では、MacにAnacondaをインストールし、LivePortraitをセットアップする手順を紹介します。Anacondaを使うことで、Pythonの仮想環境を簡単に管理できます。LivePortraitは、特にApple Silicon(M1/M2)チップ搭載のMacで動作します。

LivePortrait リポジトリ


ステップ1:Anacondaのインストール

まず、Homebrewを使ってAnacondaをインストールします。

brew install anaconda

次に、zshまたはbashシェルの初期化を行います。使用するシェルに応じて以下のコマンドを実行してください。

zshの場合:

conda init zsh

bashの場合:

conda init bash

ステップ2:LivePortraitのセットアップ

  1. LivePortrait用の仮想環境をPython 3.9で作成します。エラーが発生する場合は、conda-forgeチャンネルを使用します。
conda create -n LivePortrait python==3.9

エラーが発生した場合:

conda create -n LivePortrait python==3.9 -c conda-forge
  1. 仮想環境をアクティブにします。
conda activate LivePortrait

ステップ3:必要なパッケージのインストール

Apple Silicon搭載のmacOSで必要なパッケージをインストールします。

pip install -r requirements_macOS.txt

依存関係のエラーが発生する場合は、onnxruntime-siliconを個別にインストールし、そのバージョンでrequirementsファイルを書き換えます。

pip install onnxruntime-silicon
vim requirements_macOS.txt  # 必要に応じて編集
pip install -r requirements_macOS.txt

ステップ4:Git LFSのインストール

Git LFS(Large File Storage)をインストールします。これにより、大きなファイルを扱いやすくなります。

公式サイト: https://git-lfs.com/

brew install git-lfs

ステップ5:Fast Hands-on

以下のコマンドを実行して、LivePortraitを実行します。 (コメントを読むと NVIDIA GPU 詰んだマシンが欲しくなる...)

# For macOS with Apple Silicon, Intel not supported, this maybe 20x slower than RTX 4090
PYTORCH_ENABLE_MPS_FALLBACK=1 python inference.py

この時点でFFmpegがインストールされていない場合、エラーが発生します。


ステップ6:FFmpegのインストール

FFmpegをインストールします。

brew install ffmpeg

再度、実行します。

python inference.py -s assets/examples/source/s9.jpg -d assets/examples/driving/d0.mp4

以上で成功です。


この手順に従えば、Mac上でLivePortraitをスムーズに試すことができるはず!

ERCを読んでみよう

そもそも

2014年に Block Chain(もとい Bitcoin) の概念に初めて触れて、特別難解なアルゴリズムではなく基礎的な要素技術の組み合わせで実現される Proof Of Work の仕組み等に感動したものの、当時の業務に活きるソリューションではないと自分の中で結論づけて放置してみたらおよそ8年も経ってしまっていた。

その間、 Block Chain を核とした新たなプロダクトやサービスの拡大・進展が凄まじく、今や無視できないものとなってしまったのでいよいよちゃんと勉強しようということで、もはや人口に膾炙した感もある「トークン」や「NFT」を実現する技術を理解すべく、現時点ではその界隈の雄である Ethereum の仕様を読んでみようと思い立ったのである。

そこで ERC

なんだか「トークン」とか「NFT」という言葉が流行りすぎているせいでググっても生煮えの記事ばかり出てくる。そういう時は原典に当たりましょうということで、Ethereum の仕様たる ERC を読んでみたいと思う。

インターネットの仕様を記述したものは Request For Comments で RFC。Ethereum の仕様は Ethereum Request for Comments で ERC。

Ethereum の仕様策定に際して起こっていることをざっくり把握するにはこのポストを見ればざっくり掴めそう。

オフィシャルな ERC はこのページ のものを見れば良さそうなので ERC20 とか ERC721 あたりから読んで行こうかと思います。

ちなみに

NFTの教科書 という本を買って読んでみたものの、期待していた内容ではなかった。

前半は2020年後半から2021年半ばにかけての NFT 関連サービスやそれらが乗っている Chain の紹介(いわゆるメタバース系の事例も紹介されている)で後半が法律の解説。

前半は「そういうサービスや Chain もあるんだ〜」くらいには楽しめるものの、それぞれが特別深く掘り下げられるわけではないので時間があれば「NFT サービス」とかでググるだけでもても同じ体験が得られそう。

正直後半は接客、販売、エンターテイメント領域に携わっていれば基本的に勉強する内容で、それらの法律をもってトークンや NFT という新しい概念がどう解釈されるかに関しては「事例がないからまだわからない」的な結論が多く、残念だった。

GCEのインスタンスからGCSまたはBigQueryにデータを送る方法

この投稿は

GCPのドキュメントをよく探ればちゃんと書いてあるけどすぐに見つけられないときのための備忘録。

to GCS

ライブラリのインストール

インスタンスの状態によって諸々違うでしょうが自分がやった手順のメモ。

Python 使う前提。

sudo apt-get install -y python3-pip
sudo pip3 install --upgrade google-cloud-storage

cf: https://cloud.google.com/storage/docs/reference/libraries

サンプルコードをパクる

ここ を見れば良いだけ。

Python ならそのまま使えるコードがここにある。

destication_blob_name には bucket 名以下の path(に見えるもの)を指定すれば良い。

to BigQuery

ライブラリのインストール

sudo pip3 install google-cloud-bigquery

※ちなみにこのライブラリのインストール完了まで結構時間がかかる。 grpcio のライブラリのビルドに時間がかかるようなのでこれだけ別途落としてくると時間短縮できそうだが1時間もかからないので放置でもOK。

サンプルコードをパクる

Python でそのまま使えるサンプルコードはここ

アップロードもとのファイル形式を変えたり job config いじるときは公式のドキュメントを見る。

JSON ファイルからアップロードしたい場合は

job_config = bigquery.LoadJobConfig(
    source_format=bigquery.SourceFormat.NEWLINE_DELIMITED_JSON, autodetect=True,
)

とかしておけば良い。

参照

to GCS

to BigQuery

VuePressでブログを再開するよ

びっくりすることに最後にこのブログに投稿してから4年以上が経過している。

どうやらその間にもブログをいじろうとした形跡が見つかったが何かしらの理由で断念したらしい。

おそらくその当時の自分と似たような動機(Octopressから移行したい)で Hugo に移行させようと GitHub から clone してきたら VuePress に移行しようとした痕跡が残っていて VuePress というものの存在を思い出し、Vue ベースなら扱いやすそうだと昔の自分に乗っかることにした。

VuePress は v2 の時代

今は VuePress v2 なるものがあるらしい。特に気づいてなかったけどセットアップを進めていたら最新版の 2.0.0-beta.35 をインストールしていた。

まぁとにかく ガイド が分かりやすいので読んでいけばなんとかなる。昔の自分が何にハマったのかよくわからん。

Archive ページを作るのがちょっと面倒い

ここ に VuePress 向けの theme がまとまっているけどいまいちイケてるのがない。

というかデフォルトの theme が Vue 感強くて結構良い感じなのでそのまま使う。

ただ VuePress は別にブログに特化してるわけではないので過去の記事一覧みたいなページをサクッと設定できない。

なので自分でサクッと書いてみようと思いきやしれっと「$site.pages はもう使えないよ」って書いてあって戦意を失う。

For scalability concern, $site.pages is not available any more.

そんなわけで vuepress-plugin-use-pages を使わせていただきました。

今後は

久々にブログをいじったら色々分かりやすく便利になっていて楽しくなったのでちょくちょく投稿するかも。

あとはタグを収集できる機能が欲しいから時間があったら見てみようかな。

昔の記事をちょろっと見ると恥ずかしいこと書いてるのでこの記事もいずれ恥ずかしい記事になるでしょう。

Node.jsとnpmのインストール

手元の Mac に Node.js と npm がインストールされていなかったのでインストールした手順

homebrew を使って nodebrew をインストール

$ brew install nodebrew
==> Downloading https://github.com/hokaccha/nodebrew/archive/v0.9.2.tar.gz
==> Downloading from https://codeload.github.com/hokaccha/nodebrew/tar.gz/v0.9.2
######################################################################## 100.0%
==> /usr/local/Cellar/nodebrew/0.9.2/bin/nodebrew setup_dirs
==> Caveats
Add path:
  export PATH=$HOME/.nodebrew/current/bin:$PATH

To use Homebrew's directories rather than ~/.nodebrew add to your profile:
  export NODEBREW_ROOT=/usr/local/var/nodebrew

Bash completion has been installed to:
  /usr/local/etc/bash_completion.d

zsh completion has been installed to:
  /usr/local/share/zsh/site-functions
==> Summary
🍺  /usr/local/Cellar/nodebrew/0.9.2: 7 files, 34.4K, built in 2 seconds

nodebrew がインストールされたことを確認

$ nodebrew -v
nodebrew 0.9.2

Usage:
    nodebrew help                         Show this message
    nodebrew install <version>            Download and install a <version> (compile from source)
    nodebrew install-binary <version>     Download and install a <version> (binary file)
    nodebrew uninstall <version>          Uninstall a version
    nodebrew use <version>                Use <version>
    nodebrew list                         List installed versions
    nodebrew ls                           Alias for `list`
    nodebrew ls-remote                    List remote versions
    nodebrew ls-all                       List remote and installed versions
    nodebrew alias <key> <version>        Set alias to version
    nodebrew unalias <key>                Remove alias
    nodebrew clean <version> | all        Remove source file
    nodebrew selfupdate                   Update nodebrew
    nodebrew migrate-package <version>    Install global NPM packages contained in <version> to current version
    nodebrew exec <version> -- <command>  Execute <command> specified <version>

Example:
    # install from binary
    nodebrew install-binary v0.10.22

    # use a specific version number
    nodebrew use v0.10.22

    # io.js
    nodebrew install-binary io@v1.0.0
    nodebrew use io@v1.0.0

インストールできる Node.js のバージョンを確認

$ nodebrew ls-remote
Unescaped left brace in regex is deprecated, passed through in regex; marked by <-- HERE in m/#{ <-- HERE release}/ at /usr/local/bin/nodebrew line 731.
v0.0.1    v0.0.2    v0.0.3    v0.0.4    v0.0.5    v0.0.6    

...

io@v3.3.0 io@v3.3.1 

バージョンを指定してインストール (binary を指定したほうがインストールにかかる時間が短いようだ)

$ nodebrew install-binary v6.11.3
Unescaped left brace in regex is deprecated, passed through in regex; marked by <-- HERE in m/#{ <-- HERE platform}/ at /usr/local/bin/nodebrew line 731.
Unescaped left brace in regex is deprecated, passed through in regex; marked by <-- HERE in m/#{ <-- HERE release}/ at /usr/local/bin/nodebrew line 731.
Unescaped left brace in regex is deprecated, passed through in regex; marked by <-- HERE in m/#{ <-- HERE arch}/ at /usr/local/bin/nodebrew line 731.
Unescaped left brace in regex is deprecated, passed through in regex; marked by <-- HERE in m/#{ <-- HERE version}/ at /usr/local/bin/nodebrew line 731.
fetch: http://nodejs.org/dist/v6.11.3/node-v6.11.3-darwin-x64.tar.gz
Warning: Failed to create the file 
Warning: /Users/sojiro/.nodebrew/src/v6.11.3/node-v6.11.3-darwin-x64.tar.gz: 
Warning: No such file or directory

curl: (23) Failed writing body (0 != 792)
download faild: http://nodejs.org/dist/v6.11.3/node-v6.11.3-darwin-x64.tar.gz

自分でインストール先のディレクトリを作らないとダメらしい

$ mkdir -p ~/.nodebrew/src

再度インストール

$ nodebrew install-binary v6.11.3
Unescaped left brace in regex is deprecated, passed through in regex; marked by <-- HERE in m/#{ <-- HERE platform}/ at /usr/local/bin/nodebrew line 731.
Unescaped left brace in regex is deprecated, passed through in regex; marked by <-- HERE in m/#{ <-- HERE release}/ at /usr/local/bin/nodebrew line 731.
Unescaped left brace in regex is deprecated, passed through in regex; marked by <-- HERE in m/#{ <-- HERE version}/ at /usr/local/bin/nodebrew line 731.
Unescaped left brace in regex is deprecated, passed through in regex; marked by <-- HERE in m/#{ <-- HERE arch}/ at /usr/local/bin/nodebrew line 731.
fetch: http://nodejs.org/dist/v6.11.3/node-v6.11.3-darwin-x64.tar.gz
######################################################################## 100.0%
Install successful

インストールされたバージョンを確認

$ nodebrew list
v6.11.3

current: none

使うバージョンを設定

$ nodebrew use v6.11.3
use v6.11.3

コマンドにパスを通す

$ echo 'export PATH=$PATH:/Users/sojiro/.nodebrew/current/bin' >> ~/.bashrc
$ source ~/.bashrc 

node 及び npm がインストールされたことを確認

$ node -v
v6.11.3

$ npm -v
3.10.10

値オブジェクトとコレクションオブジェクト

某先輩の書評を読んで気になったので 『現場で役立つシステム設計の原則』 という本を読んだ。

とあるプロジェクトでその先輩に自分の書くコードについて色々ご指摘をいただいていたタイミングであり、自分としてはかなり参考になった点があるので備忘も兼ねて書いてみる。

今回は特に「値オブジェクト」と「コレクションオブジェクト(ファーストクラスコレクション)」について。

値オブジェクト

値オブジェクトはアプリケーションに登場する様々な値に対してその値を扱うための専用クラスを作るという考え方。

値ごとにクラスを定義する

値オブジェクトの考え方をルール化すると、「プリミティブ型や String 型は使わない」という方針となる。

例えば、先述のプロジェクトのコードでは登場する様々な値を String 型で表現していた。

  • userId
  • nickname
  • address
  • etc...

これらはサーバーリクエストの口でバリデーションを通るものの、その後の値がアプリケーションコード内で保証されないため非常に不安定だった。

また、例えば nicknameaddress を引数として受け付けるメソッドがあったとすると

public User hoge(String nickname, String address) {
    ...
}

となるわけだが、この時このメソッドを使う側で間違えて address, nickname の順で引数を指定したとしてもこのメソッドはその引数を受け付けてしまう。

そこで Nickname クラスと Address クラスを定義するというのが値オブジェクトの考え方だ。

class Nickname {
    static final int MIN_LENGTH = 1;
    static final int MAX_LENGTH = 20;

    String nickname;

    Nickname(String nickname) {
        if (nickname.length() < MIN_LENGTH) {
            throw new IllegalArgumentException("nickname length must be at least" + MIN_LENGTH);
        }
        if (nickname.length() > MAX_LENGTH) {
          throw new IllegalArgumentException("nickname length must be under" + MAX_LENGTH);
        }
        this.nickname = nickname;
    }
}

address に対しても同様にクラスを定義して先ほどのメソッドを

public User hoge(Nickname nickname, Address address) {
    ...
}

とすればより堅い実装となる。

値オブジェクトを不変とする

値オブジェクトの値は上書きしないというのも値オブジェクトを扱う上で重要な考え方で、これをルール化すると、「値を変更する度にオブジェクトそのものを新しく(別のオブジェクトに)する」ということになる。

Nickname nickname = new Nickname("sojiro");
nickname.setNickname("shin-sojiro");

ではなく

Nickname nickname = new Nickname("sojiro");
Nickname updatedNickname = nickname.update("shin-sojiro");

とすることで、各オブジェクトがどの値をもっているのかが明確となり、知らないうちに値が変わっている、ということを防ぐことができる。

コレクションオブジェクト(ファーストクラスコレクション)

値オブジェクトの考え方を発展させ、コレクション型のデータとロジックを独自のクラスに切り出す考え方をコレクションオブジェクト、もしくはファーストクラスコレクションという。

List<User> users = new ArrayList<>();
users.add(user);

のように扱っていた User のコレクションを、 Users というクラスを定義し、そのクラスで操作が完結するようにする。

class Users {
    List<User> users;

    Users(List<User> users) {
        this.users = users;
    }

    Users add(User user) {
        List<User> userList = new ArrayList<>(users);
        return new Users(userList.add(user));
    }

    List<User> asList() {
        return Collections.unmodifiableList(users);
    }
}

ここでのポイントは、

  • 値オブジェクトで値に変更がある場合は常に新しいオブジェクトを返したように、コレクションオブジェクトでもコレクションに変更がある場合は新たなオブジェクトを返すようにすること
  • コレクションへの参照を返す場合はなるべく変更できない状態にして返すこと

コレクションへの操作を独自クラスに閉じ込め、同一オブジェクトが持つコレクションの内容が変化することのないようにすることでより堅い実装とすることができる。

感想

Perl からプログラミングを始めたこともあってか(言い訳)、オブジェクト指向と言っても型への意識は低く、如何にコンパイル時点でバグを見つけられる堅い実装とするか、その変数に今どのような値が入っているかをコードの書き方で明確にするか、というような意識も低かった。

現場で役立つシステム設計の原則 からは他にも学んだ点が多いので追って記事にできたらと思う。

参照

現場で役立つシステム設計の原則

WordPress on GAE

GCP の事前準備

以下の準備が事前に必要。ここでは割愛。

  • GCP アカウントの作成
  • GCP プロジェクトの作成
  • 課金の有効化
  • GCS(Google Cloud Storage)に default bucket を作成
    • default bucket: YOUR_PROJECT_NAME.appspot.com
  • Google Cloud SDK のインストール
    • https://cloud.google.com/sdk/

Composer のインストール

Composer は PHP のパッケージ管理ツール

Composer is strongly inspired by node's npm and ruby's bundler.

node の npm、ruby の bundler に強く影響を受けているようだ。

手順

PHP がインストールされていることを確認

$ php -v
PHP 5.5.38 (cli) (built: Aug 21 2016 21:48:49) 

こちら の手順通り Composer をインストール

$ php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
$ php -r "if (hash_file('SHA384', 'composer-setup.php') === '669656bab3166a7aff8a7506b8cb2d1c292f042046c5a994c43155c0be6190fa0355160742ab2e1c88d40d5be660b410') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;"
$ php composer-setup.php
$ php -r "unlink('composer-setup.php');"

グローバルに呼び出せるようにしておく

$ mv composer.phar /usr/local/bin/composer

GCS へのアクセス権限変更

作成したプロジェクトでログイン

$ gcloud auth login
$ gcloud config set project YOUR_PROJECT_NAME

GCS のアクセス権更新

$ gsutil defacl ch -u AllUsers:R gs://YOUR_PROJECT_NAME.appspot.com

DB の setup

Cloud SQL を使うので GCP の SQL メニューへ

  • wp という名前で MySQL のインスタンスを立てる
    • このとき第2世代を選択可
    • 日本向けがメインであればリージョンは asia-northeast1
    • マシンタイプは安さ重視なら db-f1-micro とする (このタイプで 30円/日 という印象)
    • 他の設定はお好みで...
  • 立てたインスタンスに wp という名前のデータベースを作る
  • wp というユーザーを作る
    • アクセス制御 → ユーザー → ユーザーアカウントを作成、とたどる

WordPress の setup

ローカルに WordPress 構築に必要な素材を用意する

$ git clone https://github.com/GoogleCloudPlatform/php-docs-samples.git
$ cd php-docs-samples/appengine/wordpress/
$ composer install

setup の開始

$ php wordpress-helper.php setup
# ここでいろいろインタラクティブに聞かれるので答える

※ リージョンを聞かれるが、 asia-northeast1 がない場合は適当に答えておく

DB_HOST 設定を変更

上記手順で WordPress setup 時に適切なリージョンが指定できなかった場合には自分で一部設定を変更する

cd YOUR_PROJECT_NAME/
vim wordpress/wp-config.php

/** Production login info */ 以下の DB_HOST を適切なリージョンを用いて変更する

Deploy

GAE インスタンスに WordPress を deploy する

$ gcloud app deploy --promote --stop-previous-version app.yaml cron.yaml

最初はかなり多くのファイルを GCS にあげるのでそこそこ時間がかかる

参照

https://github.com/GoogleCloudPlatform/php-docs-samples/tree/master/appengine/wordpress

Unix timeの扱い

Unix time を日付及び時刻に変換したいこと、日付及び時刻を Unix time に変換したいことがある。

Unix time からの変換

$ date -r 616388399
1989年 7月14日 金曜日 11時59分59秒 JST

日付からの変換

$ date -jf '%Y-%m-%d %H:%M:%S' '1989-07-14 11:59:59' +%s
616388399

Could not open the requested socket エラーが出たら

Android Studio で GAE に乗せるアプリを開発しているとき、ローカルで立ち上げようとすると以下のようなエラーが出た

Could not open the requested socket: Address already in use
Try overriding --address and/or --port.

どうやら以前立ち上げた際のプロセスが生き残っていて邪魔しているらしい

以下のように対応した

Android Studio のメニューから RunEdit Configurations... とたどり、対象 module が使っている port を確認

ポートを指定してプロセスを確認、そして kill

$ lsof -i:8080
COMMAND   PID    USER   FD   TYPE             DEVICE SIZE/OFF NODE NAME
java    74792  sojiro   48u  IPv6 0xXXXXXXXXXXXXXXXX      0t0  TCP *:http-alt (LISTEN)
$ kill -9 74792