rbsecp256k1 gemについて調べてる (2)

前回の記事: https://tanaken0515.hatenablog.com/entry/2022/12/30/180910

よくわからなくなってきた(自分が何を試したのかわからなくなってきた)ので、もう一度状況を整理するために書いています。

①まずは rbsecp256k1 gem のリポジトリをforkして、forkしたリポジトリをローカルにcloneした

% git clone git@github.com:tanaken0515/rbsecp256k1.git
# ログは割愛

% cd rbsecp256k1

% git status
On branch master
Your branch is up to date with 'origin/master'.

nothing to commit, working tree clean

Ruby 3.2.0 を入れて、RubyGemsのバージョンが3.4以上であることを確認した

% rbenv install 3.2.0
# ログは割愛

% rbenv local 3.2.0
# ログは割愛

% ruby -v
ruby 3.2.0 (2022-12-25 revision a528908271) [arm64-darwin20]

% gem -v           
3.4.1

③rbsecp256k1 gemの利用に必要なライブラリを入れた

ref: https://github.com/etscrivner/rbsecp256k1#macos

% brew install automake openssl libtool pkg-config gmp libffi

④rbsecp256k1 gemの開発に必要なgemをインストールした

ref: https://github.com/etscrivner/rbsecp256k1#setup

% make setup

実態は bundle install しているだけです

ref: https://github.com/etscrivner/rbsecp256k1/blob/456ea9fa4b7829f58f00cb5df99142f07da1cc3b/Makefile#L32-L33

コンパイルした

ref: https://github.com/etscrivner/rbsecp256k1#compiling-extension

% make build
bundle exec rake compile
cd tmp/arm64-darwin20/rbsecp256k1/3.2.0
/Users/kentarotanaka/.rbenv/versions/3.2.0/bin/ruby -I. -r.rake-compiler-siteconf.rb ../../../../ext/rbsecp256k1/extconf.rb
Downloading libsecp256k1.zip 
Running 'chmod' for libsecp256k1 0.0.0... OK
Running 'autogen' for libsecp256k1 0.0.0... OK
Running 'configure' for libsecp256k1 0.0.0... OK
Running 'compile' for libsecp256k1 0.0.0... OK
Running 'install' for libsecp256k1 0.0.0... OK
Activating libsecp256k1 0.0.0 (from ports/arm64-apple-darwin20.6.0/libsecp256k1/0.0.0)...
checking for whether -I/Users/kentarotanaka/Documents/Repositories/github-com/rbsecp256k1/tmp/arm64-darwin20/rbsecp256k1/3.2.0/ports/arm64-apple-darwin20.6.0/libsecp256k1/0.0.0/include is accepted as CFLAGS... yes
checking for whether -fPIC is accepted as CFLAGS... yes
checking for whether -Wno-undef is accepted as CFLAGS... yes
checking for whether -Wall is accepted as CFLAGS... yes
checking for whether -Wl,--no-as-needed is accepted as LDFLAGS... no
checking for -lsecp256k1... yes
checking for -lgmp... no
checking for secp256k1_recovery.h... yes
checking for secp256k1_ecdh.h... yes
creating Makefile
cd -
cd tmp/arm64-darwin20/rbsecp256k1/3.2.0
/usr/bin/make
linking shared-object rbsecp256k1.bundle
cd -
/usr/bin/make install target_prefix=
/usr/bin/install -c -m 0755 rbsecp256k1.bundle /Users/kentarotanaka/Documents/Repositories/github-com/rbsecp256k1/lib/rbsecp256k1
cp tmp/arm64-darwin20/rbsecp256k1/3.2.0/rbsecp256k1.bundle tmp/arm64-darwin20/stage/lib/rbsecp256k1/rbsecp256k1.bundle

⑥ローカル環境でrbsecp256k1 gemをビルドしてインストールした

% make install
gem build rbsecp256k1.gemspec
  Successfully built RubyGem
  Name: rbsecp256k1
  Version: 5.1.0
  File: rbsecp256k1-5.1.0.gem
gem install rbsecp256k1-*.gem
Building native extensions. This could take a while...
Successfully installed rbsecp256k1-5.1.0
Parsing documentation for rbsecp256k1-5.1.0
Done installing documentation for rbsecp256k1 after 1 seconds
1 gem installed

irb を起動して rbsecp256k1 を require すると LoadError が発生することを確認した

 % irb

irb(main):001:0> require 'rbsecp256k1'
Ignoring debug-1.7.1 because its extensions are not built. Try: gem pristine debug --version 1.7.1
Ignoring rbs-2.8.2 because its extensions are not built. Try: gem pristine rbs --version 2.8.2
<internal:/Users/kentarotanaka/.rbenv/versions/3.2.0/lib/ruby/3.2.0/rubygems/core_ext/kernel_require.rb>:85:in `require': cannot load such file -- rbsecp256k1/rbsecp256k1 (LoadError)
        from <internal:/Users/kentarotanaka/.rbenv/versions/3.2.0/lib/ruby/3.2.0/rubygems/core_ext/kernel_require.rb>:85:in `require'
        from /Users/kentarotanaka/.rbenv/versions/3.2.0/lib/ruby/gems/3.2.0/gems/rbsecp256k1-5.1.0/lib/rbsecp256k1.rb:10:in `<top (required)>'
        from <internal:/Users/kentarotanaka/.rbenv/versions/3.2.0/lib/ruby/3.2.0/rubygems/core_ext/kernel_require.rb>:160:in `require'
        from <internal:/Users/kentarotanaka/.rbenv/versions/3.2.0/lib/ruby/3.2.0/rubygems/core_ext/kernel_require.rb>:160:in `rescue in require'
        from <internal:/Users/kentarotanaka/.rbenv/versions/3.2.0/lib/ruby/3.2.0/rubygems/core_ext/kernel_require.rb>:149:in `require'
        from (irb):1:in `<main>'
        from /Users/kentarotanaka/.rbenv/versions/3.2.0/lib/ruby/gems/3.2.0/gems/irb-1.6.2/exe/irb:11:in `<top (required)>'
        from /Users/kentarotanaka/.rbenv/versions/3.2.0/bin/irb:25:in `load'
        from /Users/kentarotanaka/.rbenv/versions/3.2.0/bin/irb:25:in `<main>'
<internal:/Users/kentarotanaka/.rbenv/versions/3.2.0/lib/ruby/3.2.0/rubygems/core_ext/kernel_require.rb>:85:in `require': cannot load such file -- rbsecp256k1 (LoadError)
        from <internal:/Users/kentarotanaka/.rbenv/versions/3.2.0/lib/ruby/3.2.0/rubygems/core_ext/kernel_require.rb>:85:in `require'
        from (irb):1:in `<main>'
        from /Users/kentarotanaka/.rbenv/versions/3.2.0/lib/ruby/gems/3.2.0/gems/irb-1.6.2/exe/irb:11:in `<top (required)>'
        from /Users/kentarotanaka/.rbenv/versions/3.2.0/bin/irb:25:in `load'
        from /Users/kentarotanaka/.rbenv/versions/3.2.0/bin/irb:25:in `<main>'

⑧ gemspec の files を書き換えてみた

前回の記事 https://tanaken0515.hatenablog.com/entry/2022/12/30/180910 で考えていた

diff --git a/rbsecp256k1.gemspec b/rbsecp256k1.gemspec
index 6b8f86b..57300bc 100644
--- a/rbsecp256k1.gemspec
+++ b/rbsecp256k1.gemspec
@@ -14,6 +14,7 @@ Gem::Specification.new do |s|
   s.homepage = 'https://github.com/etscrivner/rbsecp256k1'
 
   s.files = (
+    Dir['lib/rbsecp256k1/*'] +
     Dir['lib/**/**.rb'] +
     Dir['documentation/**.md'] +
     %w[ext/rbsecp256k1/rbsecp256k1.c ext/rbsecp256k1/extconf.rb Rakefile README.md]

⑨再度 rbsecp256k1 gem をビルドしてインストールした

% make install
# ログは⑥と同じなので割愛

irb を起動して rbsecp256k1 を require してもエラーが発生しないことを確認した

% irb         
irb(main):001:0> require 'rbsecp256k1'
Ignoring debug-1.7.1 because its extensions are not built. Try: gem pristine debug --version 1.7.1
Ignoring rbs-2.8.2 because its extensions are not built. Try: gem pristine rbs --version 2.8.2
=> true

⑪ Slack の ruby-jp ワークスペースで共有&相談した

rubygems チャンネルで「gemspec の files を書き直したらいけそうでした〜」的な感じで共有したら、hsbtさんより

や、C extension の場合はそこになくても https://github.com/etscrivner/rbsecp256k1/blob/81dcbc5033806625b934211eb4f7173710795bee/rbsecp256k1.gemspec#L23 で示したルール通りにビルドするんですよね

とフィードバックをもらいました。

⑫ rbsecp256k1 を利用しているプロジェクトで動作確認をした

rbsecp256k1 を利用しているプロジェクト(お仕事のリポジトリ)で、⑧の修正コミットが積まれた rbsecp256k1 を参照するように書き換えて動作確認をしてみたところ、LoadError が発生してしまいました。

つまり⑧の修正は解決策にはならない(問題は別にある)ということがわかりました。

⑬ 自分はなにもわかっていないということを認識した

ので、なにもわからん〜と言いながら https://guides.rubygems.org/gems-with-extensions/ を読んだりしています。

そして、とりあえず状況を整理するためにこの記事を書き始めたのでした。


引き続き調べてみますが、なんもわからんとなっているのでだれか助けて〜となっています。

とりあえず https://github.com/etscrivner/rbsecp256k1/issues にissueを立てようかしら。


などと言っていたら、2022/12/31 00:24(いまから約12時間前)に issue https://github.com/etscrivner/rbsecp256k1/issues/61 が立ってる!

そして 2022/12/31 05:37(いまから約7時間前)に https://github.com/etscrivner/rbsecp256k1/pull/66 で解決している...!!

最高じゃん! etscrivnerさんありがとうございます!

プルリクエストを読んでみます(理解できるかな〜?)

rbsecp256k1 gemについて調べてる

先日のhsbtさんの日記を読んでいて

https://www.hsbt.org/diary/20221227.html#p02

RubyGems 3.4 では C 拡張をインストール後にビルドディレクトリを make clean するようになった

タイトルが全部シリーズです。C 拡張な gem は ext ディレクトリの下に .c などを配置してその下でビルドしたのち lib にコピー(=インストール)という手続きを踏んでいます。今回 RubyGems 3.4 ではこの処理のうち、インストールが終わったあとは ext の下を make clean して不要なファイルを消すようになったんですが、この影響でいくつかの gem で動かないよ〜という報告が来たのであれこれ直していた。

https://github.com/rubygems/rubygems/issues/6205

要は ext の下を直接参照するようなコードがあって、そういう行儀が悪いコードは落ちますというものだった。最初はこれは revert した方がいいかなあとも思ったけど、数次第なら gem の方を直せばいいか、という気持ちになってきた。

ほ〜んと思っていたら、自分が携わっているプロジェクトでもこれに関係するエラーが出ているようだったので調べています。

対象のgemは https://github.com/etscrivner/rbsecp256k1 です。

とりあえず、Ruby 3.2を入れて irbrequire 'rbsecp256k1' したらエラーが出ることは確認しました。

% ruby -v
ruby 3.2.0 (2022-12-25 revision a528908271) [arm64-darwin20]

% brew install automake openssl libtool pkg-config gmp libffi  # ref: https://github.com/etscrivner/rbsecp256k1#macos
🍺 ... # brew install のログは割愛

% gem install rbsecp256k1
Building native extensions. This could take a while...
Successfully installed rbsecp256k1-5.1.0
Parsing documentation for rbsecp256k1-5.1.0
Installing ri documentation for rbsecp256k1-5.1.0
Done installing documentation for rbsecp256k1 after 3 seconds
1 gem installed

% irb
irb(main):001:0> require 'rbsecp256k1'
Ignoring debug-1.7.1 because its extensions are not built. Try: gem pristine debug --version 1.7.1
Ignoring rbs-2.8.2 because its extensions are not built. Try: gem pristine rbs --version 2.8.2            
<internal:/Users/kentarotanaka/.rbenv/versions/3.2.0/lib/ruby/3.2.0/rubygems/core_ext/kernel_require.rb>:85:in `require': cannot load such file -- rbsecp256k1/rbsecp256k1 (LoadError)                                                                                                
        from <internal:/Users/kentarotanaka/.rbenv/versions/3.2.0/lib/ruby/3.2.0/rubygems/core_ext/kernel_require.rb>:85:in `require'
        from /Users/kentarotanaka/.rbenv/versions/3.2.0/lib/ruby/gems/3.2.0/gems/rbsecp256k1-5.1.0/lib/rbsecp256k1.rb:10:in `<top (required)>'
        from <internal:/Users/kentarotanaka/.rbenv/versions/3.2.0/lib/ruby/3.2.0/rubygems/core_ext/kernel_require.rb>:160:in `require'
        from <internal:/Users/kentarotanaka/.rbenv/versions/3.2.0/lib/ruby/3.2.0/rubygems/core_ext/kernel_require.rb>:160:in `rescue in require'
        from <internal:/Users/kentarotanaka/.rbenv/versions/3.2.0/lib/ruby/3.2.0/rubygems/core_ext/kernel_require.rb>:149:in `require'
        from (irb):1:in `<main>'                                                                          
        from /Users/kentarotanaka/.rbenv/versions/3.2.0/lib/ruby/gems/3.2.0/gems/irb-1.6.2/exe/irb:11:in `<top (required)>'
        from /Users/kentarotanaka/.rbenv/versions/3.2.0/bin/irb:25:in `load'
        from /Users/kentarotanaka/.rbenv/versions/3.2.0/bin/irb:25:in `<main>'
<internal:/Users/kentarotanaka/.rbenv/versions/3.2.0/lib/ruby/3.2.0/rubygems/core_ext/kernel_require.rb>:85:in `require': cannot load such file -- rbsecp256k1 (LoadError)
        from <internal:/Users/kentarotanaka/.rbenv/versions/3.2.0/lib/ruby/3.2.0/rubygems/core_ext/kernel_require.rb>:85:in `require'
        from (irb):1:in `<main>'
        from /Users/kentarotanaka/.rbenv/versions/3.2.0/lib/ruby/gems/3.2.0/gems/irb-1.6.2/exe/irb:11:in `<top (required)>'
        from /Users/kentarotanaka/.rbenv/versions/3.2.0/bin/irb:25:in `load'
        from /Users/kentarotanaka/.rbenv/versions/3.2.0/bin/irb:25:in `<main>'

cannot load such file -- rbsecp256k1/rbsecp256k1 (LoadError) が出ていますね。

参考になる事例

同様の問題が確認されている ox という gem がありまして、こちらのissue https://github.com/ohler55/ox/issues/300 で調査され、こちらのプルリクエスhttps://github.com/ohler55/ox/pull/301 で解決に至っています。

このプルリクエストでは、このように lib/ox.rb にて .so ファイルを明示的に require しています。

begin
  require_relative 'ox.so'
rescue LoadError
  require 'ox/ox'
end

改めて今回のgemについて

/lib/rbsecp256k1.rb にて require 'rbsecp256k1/rbsecp256k1' で LoadError になっているので、 /lib/rbsecp256k1 ディレクトリ内になにがあるのか?を知りたくなりました。

とりあえず /lib/rbsecp256k1.rb にこんなコードを書き加えて、雑にデバッグしてみます。

puts '*' * 300
Dir.foreach(File.join(__dir__,'rbsecp256k1')) do |item|
  puts item
end
puts '*' * 300

gemをbuildしてirbでrequireしてみると↓のようなログが出ました。

************************************************************************************************************************************************************************************************************************************************************************************************************
.
util.rb
context.rb
version.rb
..
***************************************************************************************************************************************************************************

なんかしらの拡張ライブラリ(.so.bundle など)があるかな?思ったけれどなかったです。

一応 /lib ディレクトリも確認しておこうとおもって今度は↓でデバッグしてみました。

puts '*' * 300
Dir.foreach(File.join(__dir__)) do |item|
  puts item
end
puts '*' * 300
************************************************************************************************************************************************************************************************************************************************************************************************************
rbsecp256k1.rb
.
..
rbsecp256k1
************************************************************************************************************************************************************************************************************************************************************************************************************

先ほどと同じく .so.bundle などのファイルはないですね。

というか、手元の環境(Mac)で gem を build したときに /lib/rbsecp256k1/rbsecp256k1.bundle ファイルが作られていることに気づきました。

じゃあなんでgemにはこのファイルが無いんじゃろ...?ともう少し調べると、gemspecで files の指定が lib 配下 .rb だけになっていたのでした。。

https://github.com/etscrivner/rbsecp256k1/blob/81dcbc5033806625b934211eb4f7173710795bee/rbsecp256k1.gemspec#L16-L20

  s.files = (
    Dir['lib/**/**.rb'] +
    Dir['documentation/**.md'] +
    %w[ext/rbsecp256k1/rbsecp256k1.c ext/rbsecp256k1/extconf.rb Rakefile README.md]
  )

files に指定されていないファイルはパッケージに含まれないので、gemのビルド時に生成された .so.bundle などのファイルが lib 配下に含まれなくなっていたようです。

gemspec を書き換えるだけで解決できそう、ということがわかったので、これから改めて動作確認とプルリクエストを出そうと思います。

集めたどベントカレンダー2022

読みたいアドベントカレンダーを集めたど〜〜。

2022 Advent Calendar 2022 - Adventar

自分の発想の外側にあるなにかを毎年くれるアドベントカレンダーです。

Rubyのカレンダー | Advent Calendar 2022 - Qiita

RubyRubyistのようすがわかって便利です。今年も楽しみにしています。

Ruby 3.2のカレンダー | Advent Calendar 2022 - Qiita

@tmtmsさんによるアドベントカレンダーです。Ruby 3.2がリリースされるまで、変更点について書いてくださるとのことでこれもとても楽しみです。

PostgreSQLのカレンダー | Advent Calendar 2022 - Qiita

ここ数年で「DBのこと、PostgreSQLのこと、なにもわかってないぞ」というシーンが何度もありました。お仕事ではPostgreSQLを使ってるのでこのアドベントカレンダーも読みます。 2023年はDBのことをもっと知る年にしたいぞ。

PostgreSQL 16 全部ぬこのカレンダー | Advent Calendar 2022 - Qiita

[改訂3版]内部構造から学ぶPostgreSQL ―設計・運用計画の鉄則:書籍案内|技術評論社」の著者のひとりでもある@nuko_yokohamaさんによるアドベントカレンダーです。Commitfest 2022-11のなかからピックアップして紹介してくれるとのことで、とても楽しみです。

TypeScriptのカレンダー | Advent Calendar 2022 - Qiita

2日目の「TypeScriptで簡易データベースを実装する」が面白そうです。

あ〜「プロを目指す人のためのTypeScript入門 安全なコードの書き方から高度な型の使い方まで:書籍案内|技術評論社」の続き読まなきゃ

Denoのカレンダー | Advent Calendar 2022 - Qiita

Node.jsの作者が「いま考えるとこうしておけばよかったな〜」的な部分がいくつかあって、それを克服する新しいランタイムとしてつくったものがDenoです。 詳しくは「モダンなJavaScript/TypeScript実行環境「Deno」」で説明されています。

Slackの次世代プラットフォームでなにか作るときもDenoを使うことになりそうなので、知っておきたいなと思っています。

Slackのカレンダー | Advent Calendar 2022 - Qiita

前述の次世代プラットフォームの話もありそうなので、気になっています。

Rustのカレンダー | Advent Calendar 2022 - Qiita

今年は結局ほとんどRust書きませんでした。やっていきたい気持ちはあるので読むのが楽しみです。

以下、ペパボ関連

サービス

職種

Kaigi on Rails 2022 に参加しました

Kaigi on Rails _2022_ new - Kaigi on Rails | DoorkeeperKaigi on Rails 2022 に参加しました。

Kaigi on Rails _2022_ new

Kaigi on Rails 2022 のプレイベントです。運営チームの unasuke さんと okuramasafumi さんから Kaigi on Rails 2022 のタイムテーブルの紹介があり、そのあと有志のメンバーからの5分間LTがある、という内容でした。

運営チームに所属している同僚曰く、このイベントは rails new に明示的にバージョンを指定できる記法(たとえば rails _6.1.7_ new のような)にならって命名したそうです。2021年のプレイベントからこの表記になっていますね。

その同僚が「プレイベントのLT枠がまだ空いてますよ〜」と言っているのを聞きつけて、自分もLTに応募してみることにしたのでした。枠が空いていたこともあり、無事に応募が通りました。LTの内容はこちらです。

過去に書いたブログ記事「Rails の to_json には便利なオプションを渡せるよ - tanaken’s blog 」に基づいて発表するつもりだったので、応募した当初は「特に発表資料はつくらずに、ブログを画面共有しながら喋ろうかな〜。準備不要だし楽ちんだ〜」と思っていたんですが、話す内容を考えていくうちに「やっぱこれスライドちゃんとつくったほうがよさそうだな...」と思い至ったので突貫でつくりました。軽く発表の予行練習をしてみたら発表時間5分にはぜんぜん収まらなくて調整するなどして、結局結構ガッツリと準備をすることになったのでした。

実際当日を迎えてみると、自分以外の発表者の方々もしっかりとスライドをつくって発表時間もほぼ完璧に5分ぴったりで仕上げていたので、「あっぶね〜〜〜ちゃんと準備しておいてよかった〜〜〜〜」となりました。

てか、今回のみなさんタイムマネジメントすごくないですか?9人×5分の連続LTで時間通りに進むの結構すごくない?と思いました。

自分を除く8名の発表内容を列挙しておきます。

資料 発表者
ペアプロ開発をスムーズに進めるための Tips/pair-programming-tips-20221009 - Speaker Deck masuyama_13
Recommendations for making miscellaneous Custom Cops - 雑Custom Cop作りのススメ - Speaker Deck ydah_
GraphQL Rubyで スキーマ駆動開発を体感した話 - Speaker Deck isaka1022
初めてのDB定義 - Speaker Deck maimux2x
エンジニア目指して勉強中の人が初めてのRubyKaigi参加で受けた影響 - Speaker Deck hyumanase
Kaigi on Rails を 512 倍楽しむための「書く」技術/ How to write to enjoy Kaigi on Rails 512 times more - Speaker Deck hachiblog
Unlimited Web Services - Speaker Deck komagata
スプラトゥーンから学んだアプリ開発のヒントについて - Speaker Deck gogutan

自分の発表については、いろいろとリアクションをいただいて大変嬉しかったです。

特に onk さんが自分の発表に触れつつこのエントリ「 irb に show_source があることをもっと知らしめたい - id:onk のはてなブログ」を書いてくださったことが嬉しかったです。発表資料をつくる過程で改めて irb の show_source についても調べていたので、発表内容に盛り込みたかったのですが、できなかった(発表のもとにした自身の過去記事で show_source に触れてなかった&LT時間5分に収めるのが難しい、という理由で削った)ので、とてもありがたかったです。


当日の自分の様子: (#kaigionrails) (from:tanaken0515) until:2022-10-10 since:2022-10-09 - Twitter Search / Twitter

Kaigi on Rails 2022

本番イベントです。1日目は仕事をしながら、2日目は主にビールを飲みながら楽しく聞いていました。

聞けた発表は全体の4割くらいなのですが、その中でも印象に残ったのはこの3つです。

発表スライドの一覧をまとめてくださっている方がいたので、また改めてじっくり見ようと思います。 #KaigiOnRails 2022の発表スライドのリスト

運営チームのみなさん、発表者のみなさん、お疲れ様でした。すてきなイベントをありがとうございます。

運営チームの同僚から近日中にYouTubeに発表動画が公開されると聞きました。Kaigi on Rails - YouTubeをチャンネル登録して楽しみに待っています。

また、来年は現地とオンラインのハイブリッド開催を予定しているとのこと、楽しみですね。当日の運営でお手伝いできることがあればやっていきたいと思っていますので、Kaigi on Rails (@kaigionrails) / Twitterをウォッチして続報を待とうと思います。


当日の自分の様子: (#kaigionrails) (from:tanaken0515) until:2022-10-23 since:2022-10-21 - Twitter Search / Twitter

当日ヘルパーから見た RubyKaigi 2022

三重県津市で開催されたRubyKaigi 2022に参加してきました。

今回はじめて、当日の運営のお手伝い(ヘルパー)として参加したので、その視点で記録しておきます。

開催前

まずはヘルパーとして参加することにした経緯から。

RubyKaigi公式Twitterアカウントでヘルパーの公募がありました。

応募するきっかけがもう一歩なくてどうしようかな〜と迷っていたところ、

会社のSlackで同僚が「ヘルパーに応募しようか迷っています」と言っているのを見かけて

「迷っているなら一緒に応募しませんか!?」という謎のムーブ(自分も迷ってたくせに)を繰り出し、応募することにしました。

結果的に自分で自分の背中を押したというか、自分を客観視したのかな?という気がします。 「迷ってるならやれば良さそう」と思えて、あ、これは自分自身にこの言葉をかけてあげればよかったんだなぁと気づいたというか。

応募後、8月中旬にオーガナイザーの @a_matsuda さんからメールをいただき、正式にヘルパーとしての参加が決まりました。

運営チームのSlackチャンネルに参加し、わいわい始まりました。

開催前にSlackチャンネルでやったことは

  • Staffチケットの受け取り
    • すでにチケットを購入済みの場合はチケット種別の変更と返金
  • 名前やSNSアカウントの報告(サイト掲載用)
  • 運営資料の受け取り
  • そのほか細かい質問など

くらいですかね。About - RubyKaigi 2022 に掲載していただいたの、結構嬉しいです。

開催中

開催1日目の始発電車で東京から三重に向かい、津市の会場に到着したのは10時前でした。

運営チームメンバーのほとんどは前日(あるいはそれ以上前)に会場近辺に集まっており、当日は朝8時から集まって諸々の準備を始めていたので、自分が到着したころには運営真っ最中で、受付にてお手間を取らせてしまいました(一般チケットに紛れてStaffチケットの人が来た!みたいな)。

もしまたヘルパーをやるときには、なるべく前日入りできるように調整するか、遅れて参加する場合には業務に合流する流れを事前に決めておけると良さそうですね。

その後、オーガナイザーの @spring_aki さんにいろいろレクチャーいただいて、ヘルパー業務に合流しました。

自分の主な業務は、①ノベルティブースでノベルティの配布、②大ホールの扉の開閉、③昼食の弁当配布時の人の流れの整備、④そのほか気づいたことや呼ばれたお仕事、でした。担当を決められていたわけではないので、やれそうな仕事を拾っていったらこうなった、という感じです。

お仕事内容は2日目と3日目も大きく変わらず、昼間そんなに忙しいってこともなかったので、合間を見てセッションを聴講していました。手元の聴講メモを見ると、途中から聞いたり途中で抜けたりしたものを含めて12のセッションを聴講できたようです。

またノベルティブースでは、ペパボもお世話になっているフィヨルド@komagata さん、@machida さんとおしゃべりしたり、@swan_match さん(魔王)にキーボードを見せてもらったりしました。

全体を通してめちゃくちゃ忙しいということはなかったですが、3日目の夜のホール撤収作業は結構疲れました。大ホールと中ホールの廃棄品を回収してゴミ捨て場へのルートを何度も往復するのは汗だくになりました。ヘルスケアアプリでこの日の歩数を見てみると24,000歩でした。なかなかよく歩きましたね〜。

ヘルパーとして参加することで、RubyKaigiの裏側を垣間見ることができました。

ヘルパーを含む運営チームメンバーはみなトランシーバーをつけており、これを使って状況報告、相談、依頼などを行ないます。

トランシーバーには終日さまざまな情報が飛び交い、各メンバーがいくつもの課題を解決しているようすや、いくつもの提案をして行動しているようすを窺い知ることができました。(もちろん自分もいくつかのアクションをしました。決して多くはないですが)

そのようすを聞いていると「ああ、これまでのRubyKaigiも毎回こういうふうにして運営されてきたんだなぁ」と感じ、心の底から「うお〜〜〜感謝〜〜〜〜〜」みたいな気持ちが湧き上がってきました。興味のある方はぜひヘルパーに応募してみてください。オススメです。

開催期間中の反省点として「オンライン参加者の視点をあまり意識していなかった」点が挙げられるかなと思います。

RubyKaigi 2022は現地とオンラインのハイブリッド開催で、オンライン参加の方もかなりたくさんいました。にもかかわらず、2日目の通信トラブルの際に「オンライン参加者に向けたアナウンスが乏しかった」という気づきがありました(2日目終了時の運営集会にて)

「オンライン参加者の視点でいまRubyKaigiがどのように見えているか」という思考を常に持っていれば、「こういう案内を出した方が良いかも」という提案ができたかもしれないなと悔やまれます。

こういった反省を踏まえて、次回以降のRubyKaigiをもっと良くしていけると良いですね。

開催後

開催後はヘルパーとしての業務は特にないですが、Slackの運営チャンネルで知ったようすを紹介します。

オーガナイザーの一部の方は、翌日以降も引き続き会場に足を運んで備品の整備やスポンサーブースの備品を各社に送付する手続きなどを行なっていたようです。本当にお疲れさまです、ありがとうございます。

Slackチャンネルでは、集合写真の共有や、次回のRubyKaigiに向けたエモい話などが行なわれていました。

次回は長野県松本市ですね。楽しみです。

まとめ

当日ヘルパーから見た RubyKaigi 2022 について書いてみました。

自分はいつもRubyを使わせてもらっていてお世話になりっぱなしなので、少しでも何かできたらなぁという想いがありました。

その「何か」のひとつとして、今回ヘルパーとして参加することにしたのですが、結局、自分が貢献した何かよりもRubyKaigiからもらったモノの方がたくさんあって、またお世話になっちゃったぜ〜という感じですね。

ますます何かやっていきたくなりました。ありがとうRubyKaigi、また会いましょう。

ゲーム収録環境をつくった 〜みんなで実況編〜【LadioCast, BlackHole】

ゲーム収録環境をつくった 〜ひとり実況編〜【M1 MacBook Air, OBS Studio】 - tanaken’s blog の続編です。

今回の記事では「みんなで実況編」と題して、次の要件をすべて満たす構成については紹介します。

  • ゲーム端末の映像を録画できる
  • ゲーム端末の音声を録音できる
  • 自分の声を録音できる
  • ゲームを遅延なくプレイできる
  • 音声通話アプリの音声(=友人の声)を録音できる (New!)

結論(構成図)

はじめに「結論こうなりました!」という図を示します。図の元データはGitHubで管理しています。

電源供給

前回の記事と同様なので割愛します。

操作入力と映像出力

前回の記事と同様なので割愛します。

音声入出力

登場人物

前回の記事との差分は太字で示します。

人間

  • 自分(手、目、声、耳)
  • インターネットの向こう側の友人たち(声、耳)

ハードウェア

ソフトウェア

前提知識

今回の収録で新たに利用する「仮想オーディオデバイス」と「仮想オーディオミキサー」について説明します。

仮想オーディオデバイス

音声入出力装置をPC内に仮想的につくるソフトウェアです。音声を仮想のスピーカーに出力したり、仮想のマイクで音声を受け取ったりできるようになります。

この仮想オーディオデバイスは、音声通話アプリからの出力音声を収録ソフトウェア(OBS Studio)で収録するために必須です。

そもそもPCは、基本的には出力音声を自身への入力として受け付けることはできないようになっています。これは、出力音声と入力音声が無限ループする状態を避けるためです。

今回利用するOBS Studioには「音声出力キャプチャ」機能がありますが、これも物理オーディオデバイス(PC本体の内蔵スピーカーやイヤホン)への出力音声を収録することはできません。(設定の選択肢に出てきません)

この仕様を掻い潜って音声通話アプリからの出力音声を収録するために、その出力音声をいったん仮想オーディオデバイスで受け取ります。

OBS Studioの「音声出力キャプチャ」機能は、仮想オーディオデバイスであれば選択できるようになっているため、先ほど音声通話アプリの音を受け取った仮想オーディオデバイスを設定することで、その音声を収録することができるようになります。

仮想オーディオデバイスは、macOSではSoundflowerBlackHoleが有名です。この2つのうち、M1で使えるのはBlackHoleなので自分はこれを使っています。

サイトの手順に従って、BlackHoleの2chをインストールしておいてください。

仮想オーディオミキサー

PC内の音声入出力装置について「複数の入力音声を単一の出力装置に出力する」「単一の入力音声を複数の出力装置に出力する」といった操作ができるソフトウェアです。

仮想オーディオデバイスと組みわせて利用することで、音声を自由度高く取り扱うことができます。

今回は、仮想オーディオデバイスで受け取った音声通話アプリの出力音声を、物理デバイスであるイヤホンに流し込むために、このソフトウェアを使用します。

自分はLadioCastを利用しています。

環境構築

では、収録環境をつくっていきましょう。

基本的には前回の記事と同様なので、前回つくった「シーン」を複製して新しい「シーン」をつくると手間が少ないと思います。 「ひとりで収録」を右クリックすると、画像のように「複製」ができるのでクリックします。新しいシーンの名前は「みんなで収録」と名付けました。

電源供給

前回の記事と同様なので割愛します。

操作入力と映像出力

前回の記事と同様なので割愛します。

音声入出力

まず、

  • 自分の声が外部マイク(Blue Yeti)を経由してOBS Studioに収録される
  • Switchの音声がゲームキャプチャーデバイス(HD60 S+)を経由してOBS Studioに収録される
  • Switchの音声が外部ディスプレイを経由して自分の耳に届く

という構成は前回と同様です。

前回と違うのは

  • 自分の声が音声通話アプリを経由して友人たちの耳に届く
  • 友人たちの声が音声通話アプリを経由してOBS Studioに収録される
  • 友人たちの声が音声通話アプリを経由してイヤホン(自分の耳)に届く

という部分ですね。では、それぞれ設定していきましょう。

まずは音声通話アプリを開いてください。(今回の例ではGoogle Meetを扱います) 音声通話アプリには音声の入出力に関する設定があるはずなので、それを開きます。

音声通話アプリの入力装置に、今回使用する外部マイク(Blue Yeti)を指定します。これで「自分の声が音声通話アプリを経由して友人たちの耳に届く」はクリアです。

続いて、音声通話アプリの出力装置としてBlackHoleを指定します。(今回は「BlackHole 2ch」を指定します)

次にOBS Studioを開き、「ソース」のウィンドウで+ボタンから新しいソースを追加します。 今回は「音声出力キャプチャ」を選択し、「通話音声」と名付けましょう。

次の画面で「デバイス」を選択できるので、「BlackHole 2ch」を選択しましょう。

ここまでで「友人たちの声が音声通話アプリを経由してOBS Studioに収録される」がクリアです!

ただしこのままでは、友人たちの声が自分のイヤホンに届きません。

ここでLadioCastを開き、「BlackHole 2ch」に流れている友人たちの会話がイヤホン(Aeropex)に届くように設定します。 具体的には「入力1」に「BlackHole 2ch」を指定してその下の[メイン]ボタンをアクティブにし、「出力メイン」に「Aeropex」を指定します。

これで「友人たちの声が音声通話アプリを経由してイヤホン(自分の耳)に届く」クリアです!

設定は以上です!「ゲーム音声」「マイク」「通話音声」の大きさのバランスは「音声ミキサー」ウィンドウのスライダーで適宜調整していただくと良いと思います。

※ 余談1. ちょっと物理的にズルしてます

骨伝導イヤホンであるAeropexを使うことで、物理的にちょっとズル(というか簡略化)しています。

というのも通常のイヤホンを使うと、通話音声(イヤホンに流れてくる)と外部ディスプレイの音声を同時に聴くことはできないですよね。骨伝導イヤホンで耳が開いているので、物理的に外部ディスプレイの音も聞こえる、という特性を利用しています。

通常のイヤホン(耳を塞ぐイヤホン)を使用する場合には、オーディオミキサー(物理)を購入して外部ディスプレイからの音声出力とPCからの音声出力をオーディオミキサーで統合し、その音声をイヤホンで聴く、という構成にすると良いと思います。

※ 余談2. OBS Studioからの音声出力

前回の記事ではPC本体の音声をミュートにすることでOBS Studioからの音声出力をなくする方針を採用していたのですが、今回は音声通話アプリからの音声を聞く必要があるのでそれはできませんでした。

この対応として当初はPC本体の音声出力をBlackHoleの適当なchに逃す(どこにも出力しない)という作戦を立てていたんですが、OBS Studioの設定をいくつかいじってみると「音声ミキサー」の「音声モニタリング設定」で「モニターOFF」にするだけでOBS Studioの音声出力は無くせる(収録ではちゃんと音声を拾えてる)ということがわかったので、一旦それで行ってみることにしました。

この辺はOBS Studioの挙動が把握しきれてない(というか「モニターOFF」= モニタリングしないって意味だろうから、収録で音声を拾えちゃうのはおかしいような気もする)ので都度様子を見ながら(動作確認をしながら)やっていくことになりそうです。

完「みんなで実況編」

この記事では音声通話アプリの声も同時に収録するための設定を紹介しました。

テスト動画も撮りました。

ただ、音声通話アプリ(Google Meet)の会話相手がいなかったので、

という状態をつくりました。

結果的に、iPhoneの向こう側のニュースキャスターと会話しながらゲーム収録をする羽目になりました。

youtu.be

楽しかったです。

ゲーム収録環境をつくった 〜ひとり実況編〜【M1 MacBook Air, OBS Studio】

ゲームを収録するための環境を構築したので紹介します。

構築するにあたって満たしたい要件は次のとおりでした。

  • ゲーム端末の映像を録画できる
  • ゲーム端末の音声を録音できる
  • 自分の声を録音できる
  • ゲームを遅延なくプレイできる
  • 音声通話アプリの音声(=友人の声)を録音できる

この記事では「ひとり実況編」と題して、4つ目までの要件を満たす構成について紹介します。

すべての要件を満たす構成については「みんなで実況編」と題して、次回の記事で紹介します!お楽しみに。

結論(構成図)

はじめに「結論こうなりました!」という図を示します。図はMermaidのフローチャートを使って書いてGitHubで管理しています。

電源供給

操作入力と映像出力

音声入出力

登場人物

人間

  • 自分(手、目、声、耳)

ハードウェア

ソフトウェア

前提知識

収録環境を構築する方法を調べる過程で知ったことがたくさんありました。前提知識として知っておくと役立つと思うので書いておきます。

ゲームキャプチャーデバイス

録画をPCで行なうためには、ゲーム端末の映像と音声をPCに受け渡す必要があります。そのための装置です。「キャプチャーボード」と呼ばれているケースも観測しました。

いろいろな種類や価格帯のゲームキャプチャーデバイスが販売されていますが、自分はすでに友人が使っていて評判の良かった「Elgato Game Capture HD60 S+」を購入しました。

収録ソフトウェア

PC端末が受け取った映像や音声を収録するためのソフトウェアです。

今回のケースだと、このソフトウェアを使って

  • ゲームキャプチャーデバイスを経由して受け取ったゲームの映像と音声
  • マイクを経由して受け取った自分の声

を収録して動画ファイルとして保存することになります。

自分は検索結果によく出てくる「OBS Studio」を利用しています。(ほかのソフトウェアもあると思いますが調べていません)

仮想オーディオデバイスと仮想オーディオミキサー

ゲーム収録について調べると、SoundflowerBlackHoleなどの「仮想オーディオデバイス」や、LadioCastなどの「仮想オーディオミキサー」についての記載が多くヒットします。

が、ひとりで収録する場合は「仮想オーディオデバイス」も「仮想オーディオミキサー」も必要ありません。

これらのソフトウェアは次回の記事「〜みんなで実況編〜」で使用しますので、そちらで詳しく説明します。

環境構築

では、実際に収録環境をつくっていきましょう。

電源供給

まずはゲーム端末(Switch)、外部ディスプレイ、PC(MacBook Air (M1, 2020))をそれぞれ電源に接続しましょう。

ゲームコントローラー(Proコン)は電池がなければSwitchに繋いで充電しましょう。

ゲームキャプチャーデバイス(HD60 S+)とマイク(Blue Yeti)はPCから給電する必要があるので、USBで接続しましょう。

操作入力と映像出力

SwitchからのHDMIケーブルをHD60 S+に接続し、HD60 S+からのHDMIケーブルを外部ディスプレイに接続します。

HD60 S+はUSB経由でPCから給電されているので、この時点でSwitchのゲーム映像が外部ディスプレイに表示されるはずです(直接Switchと外部ディスプレイを接続している状態とほとんど同じです)。

ここで、PCでOBS Studioを起動しましょう。次のような画面が表示されると思います。

左下の「シーン」のウィンドウで、+ボタンから新しいシーンを作成します。適当な名前をつけましょう。この例では「ひとりで収録」と名付けました。

その右の「ソース」のウィンドウで、+ボタンから新しいソースを追加します。 「映像キャプチャデバイス」を選択し、「ゲーム映像」と名付けましょう。

次の画面で「デバイス」を選択できるので、「Game Capture HD60 S+」を選択しましょう。

すると、いま外部ディスプレイに表示されているものと同じ映像がOBS Studioに表示されているはずです。

プリセットは1920x1080が良いと思います(あとで変更もできるのでご自身の環境に合わせて設定してください)。

ここまでで映像出力の設定は完了です!簡単ですね。

この時点でOBS Studioの右下の「コントロール」ウィンドウにある「録画開始」ボタンを押すと、ゲーム映像を録画することができます。ただし、ゲーム音声は含まれていません。音声に関する設定は次の節で説明します。

※ 録画フォーマットについて

OBS Studioの録画フォーマットは、初期設定だと mkv になっています。このフォーマットで録画しても再生できるソフトウェアを持っていない場合があると思います(自分はそうでした)。その場合は、「設定」> 「出力」で、録画フォーマットを変更しておきましょう。自分はQuikTime Playerで再生できる mp4 に変更しました。

音声入出力

続いて音声の設定をしていきます。

OBS Studioの中央下の「音声ミキサー」のウィンドウに(確かデフォルトで)「マイク」という記載があると思います。これはPCの環境設定で入力装置として設定されているマイクからの音声を収録できるようになっています。これは「設定」> 「出力」> 「グローバル音声デバイス」の「マイク音声」から変更できます。

最後にゲーム音声を収録できるようにしましょう。映像のときと同様に「ソース」のウィンドウで、+ボタンから新しいソースを追加します。 今回は「音声入力キャプチャ」を選択し、「ゲーム音声」と名付けましょう。

次の画面で「デバイス」を選択できるので、「Game Capture HD60 S+」を選択しましょう。

すると「音声ミキサー」のウィンドウに「ゲーム音声」の記載が追加されているはずです。ゲーム音声が大きすぎると自分の声をかき消してしまうので、カーソルを左に動かして小さめに設定すると良いでしょう。この例では -15 dB に設定しています。

以上で設定はおしまいです!最終的にはこんな画面になっていると思います。

遅延を気にせずにプレイするために

ここまで設定すると、外部ディスプレイに表示されている映像・音声からやや遅れて(0.x秒くらい遅れて)、OBS Studioに映像と音声が出力されることに気づくと思います。これはゲームキャプチャーデバイスによる変換(ゲーム端末からの出力として受け取った情報をPCへの入力に変換する処理)があるからでしょう(詳しくないけど)。

映像に関しては外部ディスプレイを見れば良いですが、音声は外部ディスプレイとPCの両方から(しかもPCはやや遅れて)聞こえてくるので、混乱すると思います。加えてマイクに話しかけると、自分の声がOBS Studioを経由してPCから出力されることになります。

遅延しているゲーム音声と自身の話す声を聴きながらプレイするのはとてもやりづらいと思うので、PCの音声出力をミュートにすることをオススメします。(一応OBS Studioの「音声ミキサー」の「音声モニタリング設定」に出力OFFにする機能もあるんですが、なんか期待通りに動くときとそうじゃない時があるので、PCの音声出力自体をOFFにしちゃってます)

これで、外部ディスプレイの映像と音声で(つまり普段と変わらない環境で)プレイすることができます。

完「ひとり実況編」

この記事では、ひとり用のゲーム収録環境について記載しました。参考になったでしょうか?

雑談しながらゲームするの結構楽しくて、気分転換に良いな〜と思っています。

今回の設定で実際に収録してみた様子がこちらです。

youtu.be

次回の記事では「音声通話アプリの音声(=友人の声)を録音できる」という要件も加えた「みんなで実況編」をお送りします。「仮想オーディオデバイス」と「仮想オーディオミキサー」を使うのでややこしい設定になりますが、オンラインゲームの楽しい様子を収録するには大事な設定です。なるべくわかりやすく書こうと思うのでお楽しみに!ではまた!