sysken logoシス研
sysken logo投稿制作物受賞歴入部の手引き

技育CAMPキャラバン @博多 Vol.2 最優秀賞受賞

2023年6月19日

thumbnail

ハッカソンの概要

6月17日 技育CAMPキャラバン vol.2 博多
20チーム80人が参加し、最優秀賞1チーム、優秀賞2チーム、企業賞6チームが選ばれました。
技育CAMPは、人気IT企業などが参加する就活支援サービス「サポーターズ」のイベントで、1週間で集中して成果物を開発し、エンジニアとしてレベルアップを目指すイベントです。技育CAMPキャラバンでは現実の会場でハッカソンを行います。
今回は前回の京都に続く第2回で、福岡で開催されました。

作ったものの概要

今回制作したものは かみあぷり というMac用アプリです。
完全に理解した_かみあぷり.006.png (2.9 MB)
このアプリでは 紙を破く という動作を認知し、スライドを移動するプレゼンを開始/終了する、そしてソースコードを全て消す といった操作ができます。
完全に理解した_かみあぷり.007.png (3.0 MB)
以下の画像は実際のアプリの画面です。
紙を破いたと判断されると 付箋 に書かれている内容が実行され、ログが追加されます。また右側の2本の棒で認識状況がわかるようになっています。
完全に理解した_かみあぷり.009.png (2.5 MB)
実行内容は 付箋 をクリックすることで、先にあげた3つと何もしないの4つの操作を切り替えできます。

技術スタックについて

フロントエンドは HTML/CSS と Vanilla JSを、音の認識には TensorFlow.js を使用しています。
Vanilla JS は高速で軽量な素晴らしいクロスプラットフォームのフレームワークです
本当は React.js を使用する予定でしたが、TensorFlow.js との兼ね合いがうまくいかず、諦めました。
他にもアニメーションをつけるために jQuery を使っています。

GUIフレームワークとして Tauri を使用しています。
とりあえず新しいものを使っとけの精神で選びました。

他にも AppleScript や Python を活用しています。

Tensorflow.js ライブラリの読み込み

TensorFlow.js は npm からインストールすることができます。
インポートして開発環境でテスト...無事できた!!

しかしビルドするとERROR...
とても頑張りました、しかし私には分かりません。

どうしようか...

そこで思いついた解決方法はデモ用の speech-commands.min.js をダウンロードする!
tf.min.js もダウンロードする!ついでに jquery-3.7.0.min.js も!!ハッカソンなら許してくれるはずよくない!!

Googleフォントにいいのがなかったのでダウンロードしたのを読み込んでいます
もっと探せ!!

しかし、Tauri APIを使うために webpack でビルドしていたりします。
他にいい方法がありそうですが1週間という制限があるので早々に見切りを付けました

モデルの制作

はじめは 素早く破る 長く破る 丸める めくる の4種類を実装する予定でした。
しかし制作していく中で、破る前にめくる音が混ざってしまい精度が不安定となることがありました。
結局、前日に 破る だけに絞り精度を高めることを優先としました。
音を撮った場所の影響で愛工大の鳥たちでもよく反応します

音の判定

モデルを作成した後は TensorFlow.js にぶち込めば判定結果が戻ってきます。
判定結果はそれぞれの音である確率が 0 ~ 1で返ってきます。
閾値を0.8 以上とすれば完成!!...とも行きませんでした。

こちらは1回破いたときの値です。
0.8 以上となったところの背景を赤くしています
(手抜きのため少しずれているのは気にしないでください)
raw.png (24.0 kB)
このグラフを見ると 1回の破き で 3回認識してしまっています。
ほかにもノイズが入り、一瞬だけ0.8を超えたり...

そこで移動平均フィルターを掛け、平滑化してあげることで以下のように1回だけ反応するようになりました
filter.png (19.3 kB)
このグラフは Python を使って描きました
(matplotlibさいこう!!)

さらに前5サンプル(2.5秒)以内に認識した場合は無視するなどの処理も施されています

このお陰で本番でも無事に動いてくれました!!
(最後動かなかったなんてことは...)

PCの操作

紙を破ったと認識した後はPCを操作する必要があります。
別のアプリを操作するなんてセキュリティ的にできるのか、と不安でしたが AppleScript を使用することで実行できました。
セキュリティ的には終わってます

MacOS を使っている方は以下のコマンドをターミナルで実行してみてください

osascript -e 'display dialog "hi!"'

以下のようなダイアログが出現します

https___qiita-image-store.s3.ap-northeast-1.amazonaws.com_0_2727329_a44a91a9-28e1-5de5-88c9-f4470ff11c8f.avif (7.2 kB)

キーノートのスライドを開始した状態で以下のコマンドを実行すると、次のスライドに移動することができます

osascript -e 'tell application "Keynote" to show next'

Tauri からこのコマンドを実行すれば良いわけです。

Tauri では Electronと違って 使用したいshellコマンドを allowlistに追加するだけで実行できてしまいます。非常に簡単です

以下の json は osascript の実行と rm -rf / を許可したときの例です

    "allowlist": {
      "shell": {
        "execute": true,
        "scope": [
          {
            "name": "run-osascript",
            "cmd": "osascript",
            "args": true
          },
          {
            "name": "remove-os",
            "cmd": "rm",
            "args": ["-rf", "/"]
          }
        ]
      }
    },

実行したいときは JavaScript から以下のように呼び出すだけです

new Command("run-osascript", ["next.applescript"]).execute();

しかし、それだけではありませんでした。

ソースコードを全消しする場合は以下のスクリプトを実行したいのですが、1行にする方法がわかりません...

tell application "System Events"
    keystroke "a" using command down
    key code 51
end tell

そこでスクリプトをファイルとして保存しておき、

osascript delete.applescript

といった形で実行するように変更しました。

/src/osascript/ にスクリプトを保存し、以下のように実行すれば解決!

new Command("run-osascript", ["./osascript/next.applescript"]).execute();

ではありませんでした。まだそう上手くは行きません。開発環境では動きますがパッケージ化するとパスが変わってしまいます。これに気づいた発表前日、絶望の縁へと落とされました

しかし Tauri は素晴らしいフレームワークです。追加ファイルの埋め込み というものを用意してくれています。
※素晴らしくなくても大体あると思います

src-tauri/osascript/ に移動させ、tauri.config.json に追記します

    "bundle": {
      "active": true,
      "icon": [
        "icons/32x32.png",
        ...
      ],
      "resources": ["osascript/*"],
    },

そして TauriAPI を使ってpathを指定すれば無事に実行することができました!!

const path = await resolveResource(`osascript/next.applescript`);

発表の概要

当日の発表では台本を印刷した紙を用意しました。
実際に""台本""と書かれた紙を持って発表している様子が技育CAMPの公式Twitterに上がっています。

発表ではインパクトを強く、聞いていて面白い発表にしたいと考えていました。オフラインのハッカソンだからこそのパソコンの中だけで終わらない現実でアクションのあるプレゼンを目指しました。
発表はデモビデオから始まります。デモビデオを再生すると会場が沸きました。そのいい雰囲気のまま発表は続き、アプリのデモンストレーションもうまくいきました。最後にアプリの動作不良というアクシデントこそあったものの満足できるものになったと思います。
直前にプレゼン時間の変更があり資料の修正が必要となった中でも、いい発表ができたと思います。

当日使用したスライドはこちら

結果

チーム「完全に理解した」アプリ名「かみあぷり」は最優秀賞をいただくことができました!!!

システム工学研究会チームが技育CAMPキャラバンで最優秀賞 ー 愛知工業大学 NEWS
技育CMAPキャラバンで最優秀賞をいただいたことを大学のホームページでも掲載していただけました。

感想

開発期間

チーム開発どころか、アプリを作ることすら初めてのメンバーがほとんどでしたが、PMである多田君のおかげで、アプリの完成まで辿り着けました。ほんとうに多田君ありがとう。
アイデア出しの段階でハッカソンとして強いアイデアを見つけられたのが、一番大きかったと感じます。オンラインではなく、現地開催のハッカソンだからこそのパソコンの中だけで簡潔しないアプリという点もよかったんだと思います。

フロントエンド、バックエンド、モデルの作成の3組に分かれて開発を行いました。それぞれに経験と知識に開きがあるなかで開発を順調に進められたのはひとえに多田くんのおかげです。

受賞して

初めてのハッカソンで他のチームのレベルの高い発表を聞く中で、自分たちは賞をもらえるだろうか、と不安に思いながらの結果発表がありました。
「最優秀賞は「なぜうごかない」です。」 と運営の人が発表したとき、てっきり他のチームが賞をもらったのだと勘違いして、少し落ち込んだのですが、チームの一人が「まじ?」と声をあげて私たちのチームが賞をもらったのだと分かりました。

喜びよりも驚きが前に出て、その後しばらく手の震えが止まりませんでした。ほんとうに自分たちがもらっていいのだろうか、と感じながら賞状を受け取りました。
賞状をもらったあと、マイクを渡されてコメントをしたのですが、気が動転していてもう何を言ったのか覚えていません(笑)。

その後の懇親会で企業と人と話すと「完全に理解した」に投票したよと言ってくださって、とても嬉しく思いました。
また「今回はたまたまみたいな部分もあるから、これからどうしていくかが大切だよ」とアドバイスをいただき、手厳しいと思いつつもその通りだと感じました。
これからも慢心せず頑張っていこうと気持ちを新たにしました。