衆議院議員の被選挙権を得たブレスト

25歳の誕生日でしたっていうだけの話です。


最近は主に労働をしている、しているんだけどなんかうまくできてないなと感じてしまうことが多い。いろいろ話題はあると思うし言語化するのが難しいんだけど、こういう話:

  • 一を聞いて十を知る、的な空気読みムーブがわりとできる方だと自覚している
    • のが裏目に出ることがだんだん増えてきた
      • もちろんこれが役に立つこともあって、障害対応とかのときに一発で原因を当てられると気持ちいいみたいな話とかはあるんですが……
        • それはそれでどうなのかって話題はある
    • わかった気になっている事が多い、のではないか
    • ビジネスコミュニケーション的なのも下手
      • いわゆる「コミュ力」的なアレではなくて、もっと本質的なやつ
      • これは向き不向きもあるけど、スキルとして磨いていけるものだよね、という話はしているが……
      • 仕事してるときに常に意識できてないのでそりゃそうじゃんという感じはする、、
  • 苦手なことを克服していくのが苦手なのではないか
    • 飽きっぽい、諦めがち
    • 関係ないかもしれないけど昔からなにかをコツコツ続けてやり遂げたことがない気がする
      • あるか?
  • 雰囲気だけで乗り越えられなくなった瞬間に無力になる感じ

みたいなことをここ1年くらい感じ続けている。多少は自覚して行動できることも増えたような気はするけど、平均的にはまだ全然、という感じがしているし、同僚はこういうのが上手な人が多いので、比べてしまうともうちょいなんとかならんのか…… という気持ちになってしまう *1

文章にするとめっちゃダウナーだなって感じだけど、気温と気圧の変動がガバガバすぎて自律神経が滅びてるのがわるいだけの気もする。とはいえ落ち込んでいるだけではなくて、わりと真剣に課題感を感じてるし、なんとかしたい (雑) と思ってます。自我を持ったころからこういう感じだったのではないか、みたいなエリアの話でもある気もするので、そんなにかんたんな話ではない気もするけど……。参議院議員の被選挙権を得るころにはどうなってるんですかね。

それともうひとつ、運動とかしてなさすぎて体力がめっちゃ落ちてきてるという実感がやばい。筋肉もなんか滅びつつあるし、こういう感じなので自律神経が失調しがちという話もあると思う……。

ひとまず何が課題なのかわかってる (と思い込んでいる) のはそれはそれで幸せなことかもしれないなという気もしてきた。とりあえずこれは願望の一覧です: 本以外


関係ないけど今年に入ってから一番聴いた曲聴いてください:

*1:劣等感を感じてないといえば嘘になるけど、なんかそういうのとはちょっと違うのよな……

JPEG には大きく分けて 2 種類ある

JFIF: JPEG File Interchange Format

  • JPEGエンコードされた画像ファイルの形式の規格
  • バイナリエディタJPEG ファイルを開くと先頭の方に JFIF って書いてあるよね、っていうのの JFIF です
    • そうとも限らんよという話をこれからするわけですが
  • たぶんウェブで流通してる JPEG ファイルはこっちのことのほうが多いのではないかなという印象がある (根拠はまったくない)

Exif: Exchangeable Image File Format

  • Exif っていうと、なんとなくデジカメの撮影時の情報がなんか JPEG に埋め込まれてるアレのことじゃねーの、と思うんだけど、実際には Exif というのはファイルフォーマットの規格である
  • 我々がふだん Exif 情報などと呼んでいるアレは、APP1 Application Marker Segment ってとこに入っている (上記仕様の「4.5.4 JPEG圧縮データの基本構造」)
  • Exif ファイルは JPEG であるとは限らない (「3.2 Exif画像ファイル規定」「3.3 Exif音声ファイル規定」)
    • 音声!!!

上記の両者には微妙に互換性がないと思われている。それぞれの Wikipedia の項目を見るとなんとなく察しがつくかもしれないけど、Application Marker Segment の部分が別物になっている。実際の画像の部分 (曖昧な表現で逃げている) は同じっぽい。

This is because both standards specify that their particular application segment (APP0 for JFIF, APP1 for Exif) must immediately follow the SOI marker.

https://en.wikipedia.org/wiki/JPEG_File_Interchange_Format#Compatibility

JFIF では APP0 が必須で APP0 にしか言及されていないが、ExifJPEG 圧縮データでは APP1 が必須、必要に応じて APP15 までいけるで! という感じになっている (「4.5.5 アプリケーションマーカセグメント」)。

参考文献

ライブラリコンペア - masawada Advent Calendar 2019

ライブラリコンペア
『エグゼ3』より実装。データライブラリを通信相手と比較し、自分が未入手で相手が持っているバトルチップのデータを、お互いに得ることができる。
このままでは実際に入手したことにはならないが、データを入手したチップは、同時に実装された「取り寄せサービス」を利用することで(本来購入不可のも含めて)購入ができるようになる。

ロックマンエグゼシリーズ - Wikipedia

突然ですが、これを Spotify でやっていきます。

ルール

  1. id:masawada さんがギリギリ認識してなさそうな曲を僕が挙げる
    • 認識している の定義が曖昧、という問題がありますが、masawada さんが認識していると思ったら認識している、という定義でいったんいきましょう
    • どれくらいの量を挙げるべきかという話もあります、決めの問題なので今回はとりあえず合計 60 分を目安ということにしました
  2. id:masawada さんにその曲たちをピャッと試聴していただき、それぞれ N 点満点で評価していただく
    • 評価するというと大げさですが、iTunes で星 5 つつけるとしたらなんぼにしますかくらいの感じです
    • masawada さんがその曲を認識していなかったら N 点獲得、認識していたら N 点減点
      • レコメンドエンジンの評価みたいなイメージです (本当に?)
    • 最終的な合計点数になんの意味があるのかは宿題とします

それではお聴きください

masawada Advent Calendar 2019 Day. 23 on Spotify


この記事は masawada Advent Calendar 2019 23 日目でした。本当は RealityKit でサクセスしようとしたけどあまりに何もわからなかった……。昨日は id:Windymelt さんの Common Lispでマサワダを生成します - Lambdaカクテル でした / 明日は id:papix さんです。

Music.app (iTunes) が MP3 ファイルを最後まで再生できずに勝手にスキップしていくバグをなんとかする

このバグに何年も悩まされている気がするけど、ようやくだいぶマシな回避策を見つけられて嬉しい 意外とあんまり解決してない!!!!!!、という話です。どういうバグかというと、

  • 一部の MP3 ファイルが最後まで再生できない。5分とかある曲でも、3:01 とか、2:39 あたりで最後まで再生されたことになって (?) 否応なしに次の曲の再生が始まってしまう
    • iTunes の再生時間を変更できる設定とはまったく関係なく発生する
    • たぶん取り込み時のなんらか処理がぶっ壊れていて、一度そういうものとして取り込まれてしまったファイルは常にこのような挙動でしか再生されない
    • 最後まで再生されたことになる地点は、ファイルごとに固有? であり、常にその地点で最後まで再生されたことになる
      • 手動でその地点より先までシークすると、そこから先は本当に最後まで再生できる。その地点を通過しようとするときになんかおかしくなる、という雰囲気
    • iPhone などにその曲を同期してもこの壊れ方は引き継がれる
      • ビットレートが指定よりも高ければこのビットレートAAC に変換する、的な機能を有効にしていると、最初からそのぶっ壊れた地点までの AAC ファイルが iPhone に転送されてくる (3:01 とか 2:39 とかの AAC ファイルが iPhone に同期される)
        • 同期時に iTunes 内で変換してるときにやはりおかしくなっているっぽい
    • この症状が起こる MP3 ファイルは、iTunes 以外のあらゆるソフトウェアでは普通に最後まで再生できる
    • メタデータとかの雰囲気はあまり関係なさそうで、問題が起こるファイルの ID3 タグを全部剥ぎ取った状態で iTunes に取り込んでみても再現することがあった気がする
    • なぜなのかは全然わからないけど、Beatport で買った MP3 ファイルでは高確率で再現する

当然というかなんというか、英語圏でもこのバグは普通に起こっていて、Apple のフォーラムとかで無限に質問されている。"iTunes music cut off" とか、"iTunes song skips too early" とかでググるとこういうのをひたすら見ることができる。

これといった解決策はあんまり存在しないと思っていて、ライブラリファイルを再構築したらよいという説もあるけど、それをやると最初に曲をライブラリに追加した日時が全部吹っ飛んでしまうのでなるべくやりたくない。もっとも雑に回避するには、別のところで MP3 ファイルを AAC とかに変換してから取り込むとよいんだけど、本来必要なかった再エンコードで微妙に音質は悪くなるはずだし、MP3 から AACメタデータを完璧にマッピングするというのは全然自明なことではないのでとにかくこれもやらなくて済むならそれに越したことはない。

で、無駄に消耗しまくってたんだけど、ついにかなりマシな解決策を見つけた。これ。

github.com

このレポジトリに含まれる Fix Truncated Tracks.scpt を、ぶっ壊れた曲を iTunes で選択した状態で実行するとよい (Catalina だと 6 行目を contains "iTunes" then から contains "Music" then に書き換える必要がある *1 )。なんでこれで治るのかはさっぱりわからん……。

注意点としては、

  • 最初に曲をライブラリに追加した日時 は吹っ飛ぶ
    • ライブラリ全部のそれが吹っ飛ぶよりは2億倍マシなので許容できる
  • プレイリストに追加されていた情報も吹っ飛んでいる気がする
    • 一旦曲を消して、再びライブラリに追加したあとに、もともと追加されていたプレイリストの末尾に入れ直す、ということをやっているように見えるけど、なんかちゃんと動いてない?

何もわからない…… これでずっと治ればいいんだけど。


追記 (2020-01-06)

なんか ↑ の方法で微妙に治ってない気がする!!!!!! で更にまた調べてたけど、ギャップレス再生の時間を決めてるところがぶっ壊れてるのではないかという話をしてる人がいた。疲れる…………

Song playback cut off early - Apple Community


こういう感じだと行ける気がする (本当に最悪)

  1. MP3 ファイル (α) をどこかにバックアップし、もとのライブラリのディレクトリからはファイルを完全に消す
  2. バックアップした MP3 ファイルを AIFFエンコードし (β)、さらにそれに Kid3 とかでメタデータをコピーする
  3. 消したファイルの曲を Music.app で再生し、曲が見つかりません的なダイアログから 再配置 → 2. で生成した AIFF ファイル (β) を指定し、MP3 (α) が AIFF (β) に入れ替わった的な状態を作り出す
  4. バックアップしておいた MP3 ファイル (α) について、さらにバックアップを作り、Kid3 で以下のような作業を施す:
    1. メタデータ (ID3v2 タグ) をコピーする
    2. メタデータを全部消して一旦保存
    3. コピーしておいたメタデータをペーストし、また保存
    4. メタデータを Kid3 で一度書き直した的な MP3 ファイル (γ) が出来上がる
  5. AIFF ファイル (β) を削除し、また削除したファイルの曲を再生、再配置ダイアログで MP3 ファイル (γ) を指定する
  6. おわり
    • MP3 ファイルは (α) から (γ) に入れ替わっているが、Kid3 は自分が保持したいメタデータのタグをたぶん完全に取り扱えているので、事実上ファイルのメタデータタグの欠損は起こっていない
    • 最初から最後まで一貫して、ライブラリ上から曲を削除はしていない (実体であるファイルを消しているだけ) なので、Persistent ID や Date Added のような Music.app 外から操作しようがない Music.app 内のメタデータや、プレイリストへの追加状態も完全に保持される
    • MP3 ファイル (α) と (γ) の音声ストリーム部分はまったく同一であるはずなので、音質の劣化も発生しないはず

めっちゃ頑張れば自動化できる気がするけど API 用意されてる AppleScript だけじゃなくて UI 操作自動化的なやつをやらないといけない気がする?それともこういうのとシェルスクリプトをうまく組み合わせたらなんとかなるのか……?

macos - Changing the path to a file in iTunes with AppleScript - Stack Overflow

あとここまでやっても iOSバイスに同期して反映されるのかは結構微妙っぽくて、一旦同期済みのファイルをふっとばしてから再同期させたりするひつようがある……?

*1:scpt ファイルは微妙にプレーンテキストじゃないので p-r とか送ってもなという感じがする、、

Next.js で Google Analytics を使う・2019年冬

これは はてなエンジニア Advent Calendar 2019 14日目の記事です。

昨日は id:takuji31 さんの Kotlin Coroutinesをテストする - Takuji->find; でした。


最近は仕事で Next.js を使っているのですが、その中で Google Analytics による計測をどうするかという話題があったので紹介します。

前提

  • Next.js ((+ TypeScript) + Apollo Client) の話です
    • SPA 的遷移は使って無くて、都度 SSR で遷移してる
  • 僕は Google Analytics とその実装にまあまあ詳しい自信があります
  • 一方で React を完全に理解しているかというとそんな自信はない

tl;dr

自転車置き場の議論っぽい気もしますが、このような選択に至った理由について書いていきます。いろいろ悩みながらの判断という感じだったので、よりよい方法やご意見などあればぜひ教えていただけると嬉しいです!!!

そもそもどうやって Google Analytics を設置するか

Web ページに Google Analytics を導入する方法は数多存在するわけですが、ふつうはこれらの選択肢の中から選ぶことになると思います:

  1. いわゆる普通の設置タグ (gtag.jsanalytics.js) をコピペしてくる
    • もっとも無難と思われる
  2. Google タグマネージャー (GTM) を設置し、GTM の設定で Google Analytics を呼び出す
    • これも無難
  3. 利用しているフレームワークなどに合わせて、gtag.js や analytics.js の設置を肩代わりしてくれるライブラリを使う
  4. 自分で Measurement Protocol を叩く、もしくはこれをラップしたライブラリなどを使う
    • ハードコアだと思う……

gtag.js・analytics.js・GTM のどれかを利用する方法がもっともメジャーかつ支配的だと思いますが、これらのタグはだいたい自分でなんらかの状態を持っていたり、提供されている読み込み用コードの実行に副作用を持つものもあることに注意する必要があります。

たとえば、gtag.js のヘルプには以下のような記述があります:

ページビュー測定を無効化する

このコードのデフォルトの動作は、Google アナリティクスにページビュー ヒットを送信することです。ほとんどの場合はこの動作で問題ありません。サイトの各ページにコードを追加すれば、以降は自動的にページビューが測定されます。なんらかの理由で、Google アナリティクスにページビュー ヒットが送信されないようにしたい場合は、send_page_view パラメータを false に設定します。

gtag('config', 'GA_MEASUREMENT_ID', { 'send_page_view': false });

サイトに gtag.js を追加する  |  ウェブ向けアナリティクス(gtag.js)  |  Google Developers

つまるところ、gtag.js をロードしている <script> タグが不意に再レンダリングされないようする必要がある、という話なのですが、これは next/head パッケージで提供されている <Head> コンポーネントを利用することで回避できます *1。具体的にはこういう例がよく示されています:

<Head>
  <script async src={`https://www.googletagmanager.com/gtag/js?id=UA-XXXXXX-X`} />
  <script
    dangerouslySetInnerHTML={{
      __html: `
        window.dataLayer = window.dataLayer || [];
        function gtag(){dataLayer.push(arguments)};
        gtag('js', new Date());
        gtag('config', 'UA-XXXXXX-X');
      `,
    }}
  />
</Head>

"Next.js Google Analytics" とかで検索した人がたいてい見るであろう zeit/next.js の issue #160 などでもこれが紹介されていますし、前述の next-plugin-google-analytics も今の時点ではこの方式を使おうとしているようです。

というわけで、そういうの ☝️を _app.js に書くのが一番良さそう、というのがいまのところの結論です。念の為 key prop を設定してもよいかもしれません。

これはあんまりわかっていなくて *2、というのは

  • Router から routeChangeComplete(url) イベントというのが取れるのでそれを使えるはず
  • 一方で、routeChangeComplete されたタイミングではまだページのコンテンツを組み立て中ということがある
    • 具体的には、何らかの API からコンテンツを取得している最中だったりとか
    • 遷移後の URL はわかっているものの、title 要素が意図したものに置き換わってなかったりするので、遷移後の URL + 遷移前の title のページビューとして Google Analytics に送信されてしまう
      • Google Analytics で分析をするときに、ページタイトルを軸にして集計することはたまにあるはずなので、これでは困りそう
    • 何を持ってページビュー計測準備完了かというのはそのページによって異なるはずなので、外側から何かを観測してフックしたりするのは不可能な印象がある、ページのコンポーネントそれぞれでなんかやる必要がある?

どうするのがいいんでしょうかね、ページのコンポーネント

イベント計測

ここでこういうイベントを拾う、というのを React 世界でどう表現するか

どういうイベントを計測したいか、というのも場合によりけりですが、要素のクリックや視認 (imp) などを拾えるようなグッズを準備できれば大抵の場合は間に合うものと思います。で、実際にページを記述するコンポーネントにグッズを仕込んでいくわけですが、それにもいくつかのやり方があると思います:

  1. onClick などイベントハンドラに仕込む用のメソッドを用意して、計測したいポイントでそれを呼ぶことにする
    • Cons: 計測に関する話題までそのコンポーネントの責務になってしまうことで話が難しくなる (個人の感想)
  2. イベントバブリングを利用する想定で、計測対象のコンポーネントを囲むような形で設置するコンポーネントを用意する
    • <ClickTracker eventName="foobar"><Foobar /></ClickTracker> みたいな形で使う
    • Pros: 1. 案と比べて、コンポーネントごとに一つの機能を果たす世界観に近い
    • Cons: 内側で preventDefault などされるとイベント計測は発火しなくなる
    • Cons: div などが必要になるので、そのぶん HTML 要素のネストが深くなってしまう
  3. 計測対象のコンポーネントをくるむ HOC を用意する
    • Pros: 計測対象の要素にそのまま onClick なりを設定するようにすれば、2. 案と比べて余分に HTML のネストが深くなるということはない
    • Cons: HOC で onClick なりを触りたくない…… (個人の感想)
      • イベントバブリングに乗っかるのとどっちがいいのか、という話
  4. data- 属性などにイベントの情報を含めて、その属性を持つ要素に対してクリックイベントを設定する、というふうにする
    • Google タグマネージャーとこれを組み合わせることで、アプリケーションのデプロイなしで計測の設定をよしなにできるので、弊社ではまあまあこの手法が使われています
      • Google タグマネージャーによるイベントの計測は、「要素に対して一度だけ発火する」ような設定の状態が DOM 側にねじ込まれる実装になっており React などとは相性があまり良くなさそう、ということで今回は使わないことにしました
      1. 案と同様に、どのような文脈で計測されるのかという話題がコンポーネント側の責務になる

どの方式が一番適しているのかも場合によりけりなのではないかとは思っているのですが、今回はチームでの議論を経て 2. 案を選びました。

イベントを送る

実際にイベントを送信する際には、自前の軽いラッパーを通して gtag('event', ...) を直接叩く方法を選びました。

Google アナリティクスのイベントを測定する  |  ウェブ向けアナリティクス(gtag.js)  |  Google Developers

gtag() は引数にいろいろ指定することでいろいろできる、という感じの API なのですが、TypeScript を使っているのであれば DefinitelyTyped の @types/gtag.js パッケージを使うことで単純な引数のミスなんかは減らせると思います。

@types/gtag.js - npm

たびたび言及している react-ga などを使わないことにしたのは、この程度であればライブラリに頼るほどでもないかなと思ったのが理由です。

おわり

ということで、Next.js に Google Analytics による計測を実装していく中で考えたことをご紹介しました。2020 年も next-plugin-google-analytics 元年としてやっていきましょう。


はてなエンジニア Advent Calendar 2019 明日の担当は id:susisu さんです。フロントエンドネタが続きそうな気がする!

*1:Head コンポーネントは、渡された children の中身を独自のロジックで比較して実際の head タグに反映する、というような実装になっているので、同じ children を渡しっぱなしにしている限りは実際に DOM の抜き差しなどが起こることはない、という理解でいます

*2:今回はこのへんはスコープ外だったので……

最近買った CD

Share the light *CD+Blu-ray

Share the light *CD+Blu-ray

Run Girls, Run! のシングル。Share the light 完全におかしくて、バチバチのアーメンブレイク (しかも glitch しててブレイクコアに片足突っ込んでる)・ストリングス・Future Bass 的シンセが全部混ざってて完全に脳が混乱する。あとサビのまんなからへんで微妙に bed squeak 鳴ってるよね……?

【Amazon.co.jp限定】(初回盤)光の道標(特典:オリジナルデカジャケット)

【Amazon.co.jp限定】(初回盤)光の道標(特典:オリジナルデカジャケット)

  • アーティスト:鹿乃
  • 出版社/メーカー: Stray Cats
  • 発売日: 2019/11/27
  • メディア: CD

田中秀和作曲・Aire 編曲の CAFUNÉ を聴きたくて買ったけど完全によかった。メロディーは田中秀和だけど音は完全に Aire なので、これも脳がバグる感じで楽しい。鹿乃さんのウィスパーっぽい声も完全にマッチしてる感じで、これがアニメの主題歌のカップリングとしてやってくるのはいい時代 (語彙力) だなと思った。

田中秀和目当てで全然見てないアニメの主題歌を買っている……

近況、ハーモニーランド

ボーッと Netflix で「ボクらを作ったオモチャたち」*1の シーズン 2, エピソード 4 のハローキティ回を見ていたら、途中でサンリオのテーマパークについて触れられていて、急にいろいろ思い出してしまった。

www.netflix.com

www.imdb.com


ピューロランドではないほうのサンリオのテーマパークに、ハーモニーランドというのがあって、よくわからないことに大分県日出町というよくわからないところにある。

よくわからないところというのは嘘で、僕は生まれも育ちも大分なのでどこにあるのかは知っているし、なんなら子供のころに何度もハーモニーランドに連れて行ってもらった記憶があるんだけど、なぜあれがそんなにアクセスがよいわけではない大分県の、更にそんなにアクセスが良いわけでもない *2 ところにあるのか、というのは前からなんとなく疑問に思っていた。

のでなんとなく調べてたんだけど、

*1:原題: "The Toys That Made Us"

*2:大分基準だと別に最悪ということはないけど、観光客が行くには大変な場所だと思う