meowの覚え書き

write to think, create to understand

検索したいキーワードを複数の検索エンジンで一斉に検索できるchrome拡張機能を作ろう

目次

背景

私はインターネット上の調査は基本的にchromegoogle検索を用いるのだが、他の検索エンジン(例えばduck duck goやyandex)の方が欲しい情報が見つかることが経験上増えた1

色々な検索エンジンを用いるために、chromeのタブを複数開いて、いちいち同じ検索ワードを打ち込むのは面倒なので、複数の検索エンジンに対して一斉に検索できるツールが無いか探した。


スポンサードリンク

既存のツール探し(失敗)

SearchOnce

自分のほしいツールとしては、「SearchOnce」というwebサイトがドンピシャだった。使い方は簡単で、キーワードと検索したいwebサイトを選択してボタンを押せば別タブで検索結果を開いてくれる。

ロジックはシンプルで "https://検索エンジン/q=<キーワード>"というURLを各検索エンジンごとに別タブで開いているだけである。

しかし、メンテされていないのか、ほとんどのサイトでうまく開けない。たとえば、duck duck goで”hello”というキーワードで検索をしてみると、 "https://www.searchonce.net/www.duckduckgo.com/?q=hello" というURLを開き、404ページになってしまう。

Search All

chromeプラグインなどが無いか探したが、所望のものは見つからなかった。一応近いものは「Search All」である。

検索結果の表示画面上部に検索エンジン切り替えボタンを並べたナビゲーションバーを出してくれるが、できればブラウザのタブ単位で出してほしい。

ツールを探して候補を試して「これじゃない」を繰り返していたのだが、埒が明かないので自分でツールを作ることにした。

chrome拡張機能の実装

使い勝手の観点から、chrome拡張機能として作ることにした。 とはいえ私にchrome拡張機能の開発経験はないし、JavaScriptもほぼわからないので、ベースをchatGPTに生成させて細かい部分を修正した。

名前は安直に「Multi Search」とした。

「Multi Search」をchromeから呼ぶと次のようなhtmlのポップアップが出る。

このテキストフィールドに検索したいキーワードを入れてエンターキーを押すか、「Search」ボタンをクリックすると、複数のタブで検索結果が開く。下図は"hello"で検索した結果。

内部ロジックのjavascriptコードは次の通り。コアの部分だけ抜粋している。なお、拡張機能自体のリポジトリはこの記事の末尾の付録に載せた。

やってることは、SearchOnceと一緒で、18~21行目で検索エンジンのURLに検索したいキーワードを(エンコードして)くっつけて、そのURLをchromeapiで別タブで開いているだけである。

URLは 2~6行目で登録している。検索エンジンを追加したくなったらここに追加する。

おわりに

ツールを開発したことで調査の手間が減り、調査がかなりしやすくなったので満足。

付録

拡張機能githubリポジトリのページはこちら。

github.com

リポジトリをcloneして、chromeの開発者オプションをonにした上で、ディレクトリを取り込めば使えると思う。
現時点ではgoogle, duckduckgo, yandexだけ入れているが、お好みで追加いただきたい。

なお、このリポジトリは参考実装の位置づけなので、メンテはしない予定。


スポンサードリンク


  1. 悪化しているとの報告もある。 https://gigazine.net/news/20240117-google-search-worse-seo-spam/

Open xINT CTFで出題された寿司キットの食レポ

背景

  • 2022年のOpen xINT CTFの問題で「Saitaku Sushi Kit」という寿司キットを販売している海外の会社の社長を答える問題が出た
  • CTFの出題者の方曰く、「旅行先で気になって手に取ってみたが、高かったので買わなかった。食レポお待ちしています」と(冗談で)言っていたので、寿司キットを買って食べてみることにした。

注意: この記事では料理した寿司の写真を掲載しているが、あまり美しく撮れていないので不快に感じるかもしれない

入手方法

  • 様々なECサイトで売っているのだが、商品を日本への配送はできるところがなかなか見つからなかった
  • Pantryでの価格(日本円 税込、2022年11月の時点の値段)
    • 寿司キット: 2,247円
    • 配送料: 2,213円
  • 配送の日程感
    • 去年11月1日にPantryで注文した
      • 配送ステータスは出荷準備状態となった。
      • 「2~3週間で配送する」と書いてあったのだが、そこから何も音沙汰が無くかなり不安だった。
    • 11月25に Deutsche Post で出荷が完了したとメールがきた
      • ここからは荷物の現在地がわかるようになったので、本当に荷物が届くかの心配はせずにすんだ。
    • 12月10日くらい自宅に商品が届いた。
      • 注文から1.5ヶ月以内で届いたので、まだ速い方だと思う。

全体

  • 大きさ
    • 意外に大きい。新書の長辺程度はある。
    • 中はスカスカなので重心は安定していない。
  • 重さ
    • 371g。米が入っているのでちょっと重い

裏面

  • レシピが書かれている

側面

  • 賞味期限
    • 2023年7月5日
      • ヨーロッパの会社なので、日付のフォーマットは、 日/月/年 のはず。
  • また、会社名である「Ethnic Distribution」と書かれている。

その他

  • 梱包状態
    • 緩衝材に包まれていたのだが、若干凹んで届いた。

中身

  • 米2袋
    • 2袋に分かれているが、寿司酢が1袋なので、どうせ2袋一気に開けないといけない。
    • トータル250g(約1.7合)
      • 2〜4人分
  • 寿司酢
  • 醤油
  • ガリ2袋
  • わさび2袋
  • のり4枚
  • 巻きす
  • 割り箸2膳
  • レシピ
    • 箱の裏よりも細かくイラストで解説がある
    • また、別ページで調理ステップが多言語でかかれている

日本ならば、容易に調達できるものばかりである。
寿司ネタはもちろん同梱されていないので自分で用意する必要がある。

調理

寿司キットが届いてから時は経ち、2023年7月5日となった。賞味期限ぎりぎりということで、ようやく寿司を作る気になった。
寿司ネタはパッケージの例に載っていたサーモン、きゅうり、人参 を買った。
レシピのステップ通りにつくった。

注意(2回目): この記事では料理した寿司の写真を掲載しているが、あまり美しく撮れていないので不快に感じるかもしれない

酢飯づくり

  • マニュアル通り、鍋で炊く
    • もちろん炊飯器は持っているのだが、マニュアルを優先する。
  • 水の量が指示されていないので、普段自分が炊飯器で入れている量を目分量で注ぐ
    • Googleレンズ翻訳が勝手に水の分量の箇所を省略しているのかと思って原文も見たが、やっぱり分量は書かれていなかった。
  • 「研ぐ」ステップが書かれていない。
    • 炊き始めてわかったが、煮汁が白濁していたので、無洗米というわけではなさそうである。
  • 「米を湯切りせよ」と書いてある。
    • こんな記述は生まれて初めて見たかもしれない。
    • 実際に湯切りしてみたが、案の定米がこぼれる。

寿司ネタの準備

  • きゅうり、サーモン、人参は短冊状に切る。
    • 水の分量は書いていない一方で、切る長さに関しては具体的な数値が書いてある。
    • 人参は柔らかくなるまで適当に煮た

巻く

  • 文章で見るとなかなか理解しづらいので、普通に調理動画を見たほうがいいと思う。
  • また、のりの袋は口が大分せまいので、取り出す時にのりを破いてしまった。
    • 湿気にさらされる覚悟で袋を開いておくべきだった。

盛り付け

  • ここは普通の記述。

完成

食べた感想

  • シャリがべっちょべちょ
    • そのくせ芯が残っており、噛みごたえがかなり気持ち悪い。
      • リゾットに近い
    • 巻く時に米がうまく固まらず、巻き寿司の端からシャリが崩れた。
    • 何かの間違いかと思ってレシピを見返したが、特に間違って調理してしまったわけではない。
      • 海外では、この米の硬さがデフォルトなのだろうか。。。
    • すっぱさはないが、後味の形でほのかに酸味がする
  • のり
    • シャリがべちょべちょのせいで巻いている段階ですぐにふやけた
    • 味は日本の のりと同じ味
  • 醤油
    • 若干くどいので、薄める必要がある
  • ガリ
    • スーパーで売っている寿司に付属しているガリの味と遜色はない
  • わさび
    • 鼻がつんとする寸前の強さ
  • 総評
    • シャリをちゃんと作れていたならば、日本のスーパーに売っている寿司の味に見劣りしないものだった
      • 日本のメーカーが海外に向けて輸出しているのかと思うくらいに、日本の味である。
      • 当初は海外の独特の味を予想していただけに、いい意味で裏切られた
    • 裏を返せば、シャリという肝心な部分の作り方の説明が簡素だったことで、寿司全体のおいしさを大きく損なっている
      • 鍋で炊く以上、妥協はしないといけないものの、説明はもう少し改善の余地があると思う。

まとめ

  • Saitaku Sushi Kit は極めて日本の味
    • しかも寿司キットというだけあって、(巻き)寿司を家庭で作るための材料一式が揃っている。
    • 日本の寿司の味を、家庭で簡単に作れるという意味で、海外の商品としてはコスパはいいのではないかと思う。
  • ただし、米の炊き方の説明は本当に改善した方がいいと思うレベル
    • 他はよかったのに、どうしてこうなった…
    • とはいえ、私が炊飯器を使ったならば、「日本の味でした。おしまい。」になってしまうので、記事ネタとしてはこれでよかったのかもしれない。
  • 米の炊き方を差し引いたとしても、CTF運営の方の「寿司キットを買わない」という判断は正しかった
    • わざわざ日本人が日本の味の寿司を食べても、感想が出てこないと思う
  • したがって、4,500円持っていたら寿司屋へ行けばいい

以上。ごちそうさまでした。

2023年のRecon Village CTF ふりかえりメモ

記事概要

  • OSINT CTFの1つである、DEFCON31(2023年)のRecon Village CTFにチーム『pinja』のゲストメンバーとして参加した。CTFの情報、私の準備、終わった後の感想のメモを残しておく。
  • ゲストとして参加した関係上、この記事では私の範囲・権限で書けることだけを書く。

CTF 基本情報

  • 2023年 基本情報
    • 場所: オンライン中心
      • ctfスコアサーバへのリンクはオンラインで公開されていたが、一部の問題で現地のラスベガスホテルで情報収集する必要があった。
    • 日時(日本時間)
      • 8/12(土) 2:00〜8/13(日) 15:59
      • トータル 37h59m
    • 参加費: 無料
    • チームメンバ上限: 4名
    • 優勝チームへの賞品: 3Dプリンター
  • 去年との差異
    • 得点システム
      • 解かれるほど問題の配点が下がるのだが、やや変則的。すでに獲得したポイントであっても、同じ問題を他のチームが解くとその獲得ポイントが下がってしまう。
        • このシステムを戦略に組み込んで戦況を有利に進められるわけではないので、あまり必要性を感じなかった。
    • フラグサブミット回数の制限が設けられる
      • OSINT CTFは回答の総当りでフラグを取れてしまいやすいので、ほとんどの問題で回数制限が設けられたのはよいと思う。
      • 一方で回答回数を回避するために別チームをつくることをたびたび観測していた。
    • 別のコンテストの併催
  • 参加者(概算)
    • チーム数: 140チーム
    • 参加者数: 250人
  • 現地要素
    • ctf開始5時間経過後くらいに急にdecipher問題が追加される
    • 曰く、会場でバッジを渡すので、そのバッジの裏に暗号が書かれているのでそれを解読せよという問題。
      • 解読するための情報がほぼほぼなく、正解チームはゼロだった。
  • 問題の性質
    • webサービス脆弱性調査、パスワード漏洩情報調査、SNSアカウントの調査
      • OSINT問でよく出る写真の撮影場所の特定は無し。
    • 問題文は例年通り簡素。調査の方針となる文脈情報がほぼほぼ与えられていないため、仮説を構築しながら「ああでもないこうでもない」と試していくこととなる。
      • それ故に、自分の調査進捗と正解までの距離がわからない。やってる身としては、自分の調査方針が合っているのかラビットホールに嵌っているのかわからないまま長時間調査することとなり、かなり苦しい。

自分のCTFの取り組み

  • 実働

    • 以下のタイムスケジュールの水色マス。約28h。これが自分の発揮できる限界だった。
  • 使ったマシン

    • ラップトップ
    • グラボ2枚積んだ計算機
      • hashcatを実行するために急遽使用。
        • 7桁までしか試せなかった。8桁だと5日かかると出た。
  • 使用ツール
    • chrome
    • miro
      • maltegoみたいに、ソーシャル情報の関連グラフをつくるのに役立つと思って個人で使ったが、操作しづらくて役に立たなかった。多分xmindとかのほうが遥かによかったと思う
    • googleスライド
      • miro同様に関係グラフを作ってみたけど、スライドの大きさに対して文字がでかすぎて使いにくかった。
    • chatgptとかのLLMサービス
      • openaiに課金したが、全く使う余地がなかった。
        • ハルシネーションを起こすか、「わかりません」と答えるかのどちらか。
    • 漏洩パスワードの照会ができるサイト
      • 漏洩パスワードを答えさせる問題があまりにも多いため急遽課金。
      • とはいえ、運営いわく、問題は無課金で解けるものばかりらしい。
        • (去年は課金しないと解けない問題があった気がするが…)
  • 眠気覚まし
  • 戦い方
    • 自分ができることを時間いっぱいまでひたすらやっていた
      • SNS調査で候補となるアカウントをすべて調査する
      • 運営に問い合わせる

終わった後の感想

  • 難易度
    • 去年よりも難化している気がする。
      • 問題文が一層漠然になっている。
      • 「何でこれが正解なんだよ」とツッコみたくなるものも存在する。
    • ウォームアップにあたる問題がなく無慈悲。
    • 良い見方をすれば解きごたえがある
      • ただし、1問を解くのに長時間をかけることを厭わず、報われなくてもよいという覚悟が必要。
  • 問題のヒントについて
    • ctf終了後、すべてのヒントがポイント消費なしで見られるようになったので中身をみてみたが、そのほとんどが有用ではなく、消費ポイントを回収できなそうだった。
  • 所感
    • いろんなツールを準備して挑んだが、結局はガチャガチャと思いついたままに調査することに頼らざるを得なかった。
      • それでもフラグゲットできたので本当によかった。
    • 理不尽な要素に抗議したくなる時もしばしばあったが、メンバーが「運営の心理を理解できなかった」と自責に持っていく逞しさは見習いたいと思った。その他CTF全体通してチームには感謝しかない。
    • 何だか全体を通してマイナスの口ぶりになってしまったが、このくらい高い難易度のOSINT CTFは一年であまり存在しないため、非常に楽しめた。チャレンジングな問題を用意してくれたCTF運営の方に改めて感謝したい。

DEFCON Recon Village CTFの過去問まとめ

まとめがなぜかなかったので自分でまとめた。

まとめる単位は「DEFCONのナンバリング(開催年) 現地orオンライン」

ChromeのGoogleレンズの画像検索結果を他国準拠にする

(画像 左:日本準拠のGoogleレンズの結果。 右:アメリカ準拠のGoogleレンズの結果)

CTFのOSINT問を解く上で必須のツールであるGoogleレンズですが、私の環境だと日本のページを優先的に提示していたため、どのようにその傾向を変えるのか調べました。

結論としてはChromeのプロファイルにGoogleアカウントを紐付け、②そのGoogleアカウントの言語設定を変えるだけでよいです。

背景

6月にCapture The Talent と K3N4D4M5氏が共催したOSINT CTFがありました。

そのCTFの1問目は「↓の画像が撮影された公園の名前を答えよ」という、オーソドックスな問題でした。

画像の撮影場所の特定をする問題のセオリーは、画像ファイルのEXIFチェックと各種検索エンジンによる「画像で検索」にかけることなのですが、いずれも通用しませんでした。
私の過去のOSINT CTFの参加経験から考えて、1問目はセオリーに則れば解ける問題が用意されていることが多かったですし、この問題の回答者数がみるみる増えていくので、自分の調査手順に問題があると考えました。

私の調査の中で気になったのは、ChromeGoogleレンズの検索結果が日本のページばかりであることでした。このCTFは主催者は海外の方なので、この画像は日本国外で撮影された可能性が極めて高く、日本語のページでは扱われていないと考えました。

そこで、これをアメリカのページを優先的に出力するようにできるか試しました。

最初はVPNを介したり、Chromeのセンサで所在地を変えたりしてみたのですが、日本の検索結果が優先して返されるままでした。最終的にたどり着いた方法が冒頭で述べた、Googleアカウントの言語設定を変えることでした。
以下ではその方法について説明します。

言語設定の変更手順

(手順は2022/08/06時点のChromeのUIです。)

まず、ChromeのプロファイルにGoogleアカウントを紐付けておきます。

Googleアカウントを紐付けたプロファイルでChromeを開きアカウントアイコンをクリックし、「Googleアカウントの管理」をクリックします。

Google アカウント管理画面の検索フォームで「言語」と入力し、「言語」の設定ページを開きます。

「言語」の設定ページにおいて、「+ 他の言語を追加」ボタンをクリックします。

Googleレンズで検索結果を優先したい言語・国を選択します。ここでは 言語を「English」、国を「United States」としました。

現在は日本語が最優先になっているので、「↑」ボタンをクリックし、「English」を日本語より上に持ってきます。

すると、言語が変わりました。

この状態でGoogleレンズを使用します。すると、先程と同じ画像を入力したにもかかわらず、英語のページが優先的に表示されていることがわかります。

最初に紹介したOSINT問では、Googleレンズがアメリカ準拠の状態で検索範囲を車付近にフォーカスをすればフラグのページがヒットしました。

まとめ

ChromeGoogleレンズが返す結果を変える方法を説明しました。
日常でGoogleレンズを使う時に海外の結果が出るのは不便かもしれないので、OSINT CTF用のGoogleアカウントとChromeプロファイルを用意しておき、CTF中のみ、そのChromeプロファイルでGoogleレンズを使用するのがよいと思います。

地理的位置に基づく店舗名の(エセ)AND検索

画像引用元: https://tabelog.com/hiroshima/A3401/A340121/34000922/dtlphotolst/3/smp2/

この記事では、↑の写真の撮影場所の特定に挑戦した際に考案した手法について記す。具体的には、店舗名2つを指定すると距離の近い店舗ペアを列挙する手法を実装し、スターバックスコーヒーとFrancFrancが隣接する建物の特定を試みた。

先に述べておくと紹介する手法では場所の特定はできなかった。しかし、今後撮影場所の特定を行う際に流用できる可能性がある。


スポンサードリンク

続きを読む

音声認識エンジン『Julius』を使って韻を踏んだフレーズペアを探す

f:id:meow_memow:20211231223546j:plain

こちらは『創作+機械学習 Advent Calendar 20212枚目の2日目の記事です。

adventar.org

先に記事の要旨を説明すると、音声認識器の認識結果を敢えて複数個出力することで韻の近い単語1列(以下フレーズと呼ぶ)を検索するツールとして使えないか検証したという内容です。簡易的に実験した結果、狙ってフレーズを検索するのは難しいですが、面白いフレーズペアを偶発的に発見する用途には使えそうという印象です。

背景

作詞の現場で、押韻を用いた表現を探したい(韻を踏みたい)ケースがあります。例えば「思い出」の母音「o o i e」に近い言葉を探すと「遠い目」という単語が使えそうです。

語彙力が豊富な方やラッパーをなりわいとしている方であれば瞬時に言葉の候補が思い浮かぶのかもしれませんが、経験・スキル・センスが問われる作業だと思います。

そこで誰でも再現できる手順で、似たような音の響きを持つ言葉を探す方法を考えます。

既存手法と課題

考えうる方法としては2つあります。

既存手法1: 過去事例の流用

既存手法の1つめは過去事例の流用です。これはラップの歌詞やMCバトルの書き起こしから使えそうなものをストックしておくというものです。
過去事例の情報源ですが、例えば『韻ノート』には、ラッパーの踏んだ韻を含むラインが第三者により登録されていることがあります。

in-note.com

例えば”R-指定”というラッパーだと次のようなものがあります。

「しかと見ときな格の違い キッズとキングの箔の違い お前殺すぜ覚悟しな ここに転がるカスの死体

https://in-note.com/rhyme_groups/12

これならば、プロが踏んだ質の良い韻を使うことができそうです。
しかし、この方法で自分の作品を作りたいと思う人はいないと思います。質が良いということはオリジナリティも高く、やみくもに使うと”他人のパクリ”とみなされるためです。作詞作業に限らず創作界隈においてはご法度でしょう。
したがって、他人が踏んでないような韻を探す必要があります。

既存手法2: 母音に基づく検索

既存手法の2つめは母音に基づく検索方法です。
インターネット上には母音で引ける辞書サービスがあります。

kujirahand.com

たとえば「思い出」と踏みたい韻を探すために、母音“おおいえ”で検索すると、「乙姫」、「とこしえ」というものがヒットします。 また、「五ノ池」のような固有名詞もヒットします。「おおいえ」を母音とする単語単体だけでなく、さらに「おおいえ」を前後に含む単語を検索することができます。

また、"背景"の項目で紹介した「韻ノート」ならば、母音に直さずとも、韻を踏みたい単語で探せます。
試しに「思い出」で検索すると、「暴行事件」「東京事変」などという結果が提示されます。「っ(促音)」や「ー(長音)」を考慮した検索ができるので、現実の発声に即した検索ができます。

既存手法の課題

上に挙げたツールは作詞作業には十分使える一方で限界も2つあると考えます。
1つ目は基本的に1単語対フレーズ(もしくはフレーズ対1単語)でしかヒットしないことです。フレーズ対フレーズではどのようなものがあるかといえば例えば、 『夕方ノスタルジー / ZORN Feat. WEEDY』では「ラムネ の 瓶」と「鳴る メロディ」という韻を踏んでいます。3単語対2単語ですし、単語の切れ目も一致していないので先程の検索ツールではヒットしないでしょう。
2つ目はツールは母音は完全一致のみヒットすることです。 途中に1文字程度の母音が多めに入っていたり抜けていたりというものはヒットしないです。前述の『夕方ノスタルジー / ZORN Feat. WEEDY』では「賃貸マンション」と「心配無いよ」で踏んでいる箇所があります。母音こそ完全一致ではないですが、歌詞の文脈とも合わさって全く違和感がありません。

以上から、既存手法には課題は3点あると考えます。

  • オリジナリティが発生しない程度に一般的かつ新規性がありそうなものを探すこと
  • フレーズ同士の組み合わせを探すこと
  • 音が完全一致でないものも探すこと

提案手法

この課題3つを音声認識エンジンJuliusを使うことで同時に解決できないかと考えました。

julius.osdn.jp

核となるアイディアは「Juliusに実装されている、似たような音の響きを持つ単語の候補を時間区間ごとに出す機能を使う」ことです。具体的には下図の"単語グラフ"のようなイメージです。

f:id:meow_memow:20211231224528j:plain

図: 公式ページの"単語グラフ出力"より引用

このような単語の候補のグラフから、韻を踏んだフレーズペアを探すというものです。

Juliusの音声認識アルゴリズム

Juliusを使うとなぜアイディアが実現できるのか、Juliusで採用されている音声認識アルゴリズムの大まかな仕組みを知っていた方が理解しやすいと思うので説明します。(とはいえ他人に説明できるほど音声認識を理解できていないのでやんわりとですが...)

ここで覚えておいていただきたいことはJuliusの音声認識は内部で音響(何と発音されているか)と言語らしさ(言葉としての現れやすさ)をスコア付けするグラフ探索問題を解いているということです。

f:id:meow_memow:20211231224734p:plain

図: Juliusの論文より引用

  1. 特徴抽出: 入力されたディジタル音声信号から一定時間長で識別のための特徴量を連続的に抽出していきます。JuliusではMFCCという特徴量を抽出します。
  2. 音素系列の認識: 処理1で抽出した特徴量系列を音響モデル(図で音素モデルと呼んでいるもの)により、音の並びである音素2列を推定します。具体的な処理としては、音素ごとにHMMが用意されており、観測された特徴ベクトルを生成する尤度を各HMMが計算しスコアを算出します。
  3. 音素列から単語に直す: 音素列は発音辞書を用いて音素列に該当する単語が存在するかをチェックします。
    1. 発音辞書は次のようなものです: https://github.com/julius-speech/dictation-kit/blob/master/model/lang_m/bccwj.60k.htkdic
    2. もちろん「a sh i t a」を「明日」とするのか「足 田」とするかという複数の変換先がありますが、そこは手順4で確率的に決めます。
  4. 単語列の言語的確率を付与: ここまでで、音素列が単語列へと変換されていますので、言語モデルを用いて単語列に言語的観点から単語列の生成確率(スコア)を与えます。例えば「今日 の 天気」と「京都 天気」だと前者の方が確率が高く与えられます。
  5. 手順2〜4は、どのHMMから通ってきたか、どういう単語に直したかなどで探索経路が異なるため、複数のパスを候補として持ちながら探索を進めます。
  6. パスの候補の中から一番音響モデルが出したスコアと言語モデルが出したスコアの高いものを音声認識結果として提示します。

Juliusでは2パス探索を採用しており、手順2〜4を2回行います。1パスめでは始点から終点へ順方向に計算処理の軽いモデルでスコアを求めます。2パスめではより前後の文脈に応じたモデルで終点から始点へ逆方向に探索します。このとき1パス目の情報(どの時刻にどういう単語がどういうスコアであったか)をヒューリスティックとして用いることで高速に探索します。

アイディアの再掲

Juliusは音の近さと言語らしさを考慮してグラフの探索問題を解いているという点を説明しました。また、複数の経路を探索候補として保持していることや、いつの時刻に何の単語がありそうかという内部表現を保持している旨を述べました。

ということは、自分が検索したい韻を踏んだフレーズをJuliusに認識させれば、複数の認識結果やJuliusの内部表現から、音の聞こえ方が似ていて日本語としても自然な表現を集めることができるのではないかと思いました。

このアイディアを実現する方法には至ってシンプルで「Juliusの内部表現を出力するオプション3をつけて、踏みたい韻を含むフレーズを発声し、表示された結果をメモする」ことです。

Juliusで実際にフレーズペアを探す

Juliusのセットアップ

大変ありがたいことに、Juliusをすぐに試験できるように”ディクテーションキット”が公式的に用意されています。

julius.osdn.jp

”ディクテーションキット”には各OSごとのJuliusのバイナリと、日本語音声認識のためのリソース(学習済みの音響モデルと言語モデルなど)が既に同梱されており、コマンドラインからバッチを実行すればすぐに音声認識を開始することができます。

音声入力手段はデフォルトではマイク入力ですが、実行オプション(-input file)で音声データ4を指定することも可能です。

実験

認識結果上位を表示するように出力

Windows10でrun-win-gmm.batをオプションをつけながら実行してみました。

まず、自分が今踏みたい韻のフレーズを含んだセリフを音声認識し、認識のスコアの上位10つを出力してみます。 ここでは試しに「いい 思い出」に近い聞こえ方のフレーズを探してみます。

「あれはいい思い出だった」と発話した結果を記します5

sentence1:  あれ は いい 思い出 で 、 だ 。
sentence2:  あれ は いい 思い出 って 、 だ 。
sentence3:  あれ は 入り 思い出 って 、 だ 。
sentence4:  、 あれ は いい 思い出 で 、 だ 。
sentence5:  あれ は 入 思い出 で 、 だ 。
sentence6:  、 あれ は いい 思い出 って 、 だ 。
sentence7:  R Y いい 思い出 で 、 だ 。
sentence8:  あ 、 あれ は いい 思い出 で 、 だ 。
sentence9:  R Y いい 思い出 って 、 だ 。
sentence10:  あ 、 あれ は いい 思い出 って 、 だ 。

本来見つけたかった「いい 思い出」の部分はどの結果でも正しく認識されており、フレーズペアを見つけることに失敗しました。敢えて言うなら「あれ は いい」と「R Y」がフレーズ対フレーズのペアなのですが、歌詞として使えるケースは極めて限定的でしょう。

”単語ラティス形式”で出力

複数の認識結果を見ることは目が疲れるので、”単語ラティス形式”で出力(オプション-latticeをつけて実行)をしてみました。こちらは、どの区間にどのような単語がありそうかを可視化できるものです。

先程と同じく「あれはいい思い出だった」と発話した結果を記します。

-------------------------- begin wordgraph show -------------------------
   0:
   0:|-|
   1:
   0:|------|
   2:
   0:|-------|
   3:   ああ
   7:  ||
   4:   あ
   7:  ||
   5:   あー
   7:  ||
   6:   、
   7:  |-----|
   7:     、
  10:    |---|
   8:         タレ
  20:        |--------|
   9:         たれ
  20:        |--------|
  10:         多衣
  20:        |--------|
  11:         佐江
  20:        |--------|
  12:         幸い
  20:        |-----------------|
  13:         は
  21:        |---|
  14:         彼
  21:        |-------|
  15:         あれ
  21:        |--------|
  16:         彼
  21:        |--------|
  17:         かれ
  21:        |--------|
  18:         カレー
  21:        |--------|
  19:         我
  21:        |--------|
  20:         われ
  21:        |--------|
  21:         姉
  21:        |--------|
  22:         吾
  21:        |--------|
  23:         金
  21:        |--------|
  24:         腫れ
  21:        |--------|
  25:         あれ
  21:        |--------|
  26:         晴
  21:        |--------|
  27:         綾
  21:        |---------|
  28:         彩
  21:        |---------|
  29:         亜矢
  21:        |---------|
  30:         アレン
  21:        |----------|
  31:         カレン
  21:        |----------|
  32:         亜鉛
  21:        |----------|
  33:         か弱い
  21:        |----------------------|
  34:             良い
  32:            |------------------|
  35:                  の
  43:                 |------|
  36:                  は
  44:                 |------|
  37:                   は
  47:                  |-----|
  38:                    は
  49:                   |----|
  39:                         いい
  62:                        |------|
  40:                           いい
  66:                          |----|
  41:                                思い出
  79:                               |----------------|
  42:                                                 だっ
 122:                                                |-----------|
  43:                                                             た
 151:                                                            |-----|
  44:                                                                    。
 168:                                                                   |-|
-------------------------- end wordgraph show ---------------------------

やはり「いい 思い出」の部分はまとめられてしまっています。しかし、「あれ は いい」の部分に「か弱い」という表現が出てきました。母音が完全一致していないですが似たような響きの単語が偶発的に得られたと思います。

考察

自分が見つけたい韻のフレーズをピンポイントでみつけることは難しそうです。それは尤もなことで、認識結果の上位に来るものは当然似た認識結果になりやすいです。もっとスコア付けをオプションで調整し、「聞き間違え」を意図的に誘発して認識結果の多様性を上げる必要がありそうです。

このような理由から、フレーズの検索用途というよりも、何らかの音声を”単語ラティス形式”形式で垂れ流しておき、作詞に使えそうなフレーズペアを偶発的に発見してそれをストックする用途の方が適しているのではないかと思います。

私の手法のその他の限界としてはJuliusの学習モデルの制約が考えられます。例えば語彙は bccwj.60k.htkdic 内の単語に制限されています。このファイルに単語を追加することもできますが、言語モデルには含まれていないため、未知語の確率が割り振られ認識結果に出る確率が下がり認識結果としてヒットしにくいです。また、音素の連節(トライフォン)もlogicalTriというファイルで定義されており、このファイルに載っていない音素列を含む単語は登録することができません。このように、キットを改造するには音声認識への理解やエンジニアリングが必要で高い技術力が要求されそうです。

まとめ

音声認識エンジンJuliusを用いて、フレーズ同士の韻を踏んだ表現を検索(あるいは収集)する方法について提案しました。

探したい韻のフレーズを検索する用途に用いるのは必ずしも成功しないですが、実際に作詞に使えそうなネタを偶発的に発見する用途としては使えそうであることがわかりました。もちろん作詞活動だけでなく漫才の聞き間違えネタに使えそうで、コメディと相性がよさそうです6

今回は音声認識モデルでしたが、他のタスクも同様に認識結果のうち次候補以降や推論ミスも面白い用途に使えるかもしれません。

それでは、最後まで記事を読んでいただきありがとうございました。

追記:
再掲になりますが、『創作+機械学習 Advent Calendar 2021』では、創作活動用途に機械学習技術を適用する取り組みを有志が多数公開してくださっています。どの記事も面白いので、ぜひラインナップを一読いただければと思います。

adventar.org

参考文献


  1. ここでは形態素を想定しています。

  2. 音声言語を構成する最小単位です。

  3. この中間結果出力機能があることが、数ある音声認識ライブラリの中からJuliusを選んだ理由です。

  4. サンプリングレートは16kである必要があります。

  5. airpodsのマイクで入力しているため、認識結果は悪いです。

  6. 機動戦士ガンダム 閃光のハサウェイ』冒頭事前公開でも音声認識誤りが発生し低俗な字幕が表示されたために、話題になりました。