rch850 の上澄み

技術的な話題とか、雑談とか。タイトルを上澄みに変えました @ 2020/09/02

Web Audio API の奥底から Angular とつながりたかった

Angular 2 の勉強がてらに、Web Audio API で録音するウェブアプリを作ろうとしたら、変なところでハマったのでメモ。

録音には MediaRecorder を使おうとしました。コードは今のリンク先にあるものを参考に書きました。getUserMedia で取った stream を使って MediaRecorder を作って、その onstop で結果を得る形です。

が、なかなか録音完了後の結果がビューに反映されませんでした。AngularJS 1.x で言うダイジェストをしたかったんですが、ドキュメント の Change Detection あたりを読んでも Angular zone がいい具合にやるから大丈夫と書いてあるだけでさっぱり。

いろいろ調べて Triggering Angular2 change detection manually - Stack Overflow に行き当たって ChangeDetectorRef.detectChanges() が良さそうということが分かりました。

最終的にはこのようなコードになりました。

  constructor(private ref: ChangeDetectorRef) {
    navigator.mediaDevices.getUserMedia(
      { audio: true }
    ).then((stream: MediaStream) => {
      this.mediaRecorder = new MediaRecorder(stream);
      this.mediaRecorder.ondataavailable = (e) => {
        this.chunks.push(e.data)
      }
      this.mediaRecorder.onstop = (e) => {
        let clipName = prompt("Enter a name for your sound clip")

        let blob = new Blob(this.chunks, {"type": "audio/ogg; codecs=opus"})
        this.chunks = []
        this.clips.push({
          name: clipName,
          audioUrl: window.URL.createObjectURL(blob)
        })
        console.log(this.clips)
        // これを呼び出したら clips への要素追加が反映された
        this.ref.detectChanges()
      }
    }, function(err: any) {
      console.error(err);
    });
  }

以上!

コード書き初めのつもりが環境構築で終わった

しばらくメンテしてなかった AppleSystemStatusNotifier について、色々やりたいことがたまってたのでリストアップしてみた。

  • 環境構築。現状は package.json も何もない。
  • Developer System Status も取りたい
  • Apple に対してやさしくなりたい(サーバを作ってステータスをキャッシュしておきたい)

環境構築

package.json を書いて lint ぐらいかけたいなぁと。

  • 手元に yarn が入ってなかったので brew install yarn。そしたら n を使ってるからか brew link node してねと言われたので、いったん brew link --overwrite node してもう一度 n 叩いて復旧。最後の手順は不要かも。
  • .npmrc で save = true とか save-exact = true って書いてたみたいに、何か設定しておきたいなと思っていろいろ調べてみた。でも途中で yarn なら勝手に save されるし exact なくても yarn.lock がうまいことやってくれるんじゃないかと思い始めてきて、何も書かないことにした。.yarnrc に書く方法もあるそうです。
  • なんか TypeScript にしたくなったから TypeScript にした。
  • TypeScript だから tslint を使うようにした。

ひとまずここまでの作業で参考にした記事:

ymotongpoo.hatenablog.com

Developer System Status を取りたい

  • 当初はこのページに全てのステータスが載ってたんだけど、いつからか一般向けと開発者向けに分離してた。両方見て、それぞれのステータスページを開けるようにしたい。
  • 2つの URL から取ってくる必要があるので、Promise.all でまとめたい。となると axios を使いたくなってくる。となるとパッケージをバンドルする必要が出てくる。最初のコードでは zepto.min.js を直接置いてたけど、できるならまとめちゃおう。
  • 今回は rollup を使ってみる。rollup か Webpack2 かの比較を見たところ、酷く差があるわけではなさそう。

ここらでタイムアップ。取りたいって言って取れてないですね。連休中にかたをつけたい。

Internet of Tairyoku の開発で得られた知見と経験

Mashup Battle 1st Stage in 北陸Internet of Tairyoku のプレゼンをしてきました。

DSC_0113

DSC_0116

実装的な話は質疑でちらっと触れた程度で、プレゼン内でも全然してなかったので、忘れないうちに書いておきます。

知見

制限のあるネットワーク環境で、OSX のインターネット共有が活躍する

コワーキングスペースWiFi で開発作業していたのですが、iPad の MESH アプリから Mac に立てたサーバにつなぐことができませんでした。おそらく WiFi につないでる機器間のパケットが通らないようになっているのではないかと。

テザリングすればいいんだけど、もっといい方法ないかなーと悩んでいたら、@macoshitaOSX のインターネット共有でなんとかなると教えてくれました。共有する接続経路を Wi-Fi、相手のコンピュータでのポートを Bluetooth PAN にして接続しました。iPad から見た Mac の IP アドレスも変わらない(試している限りでは)ため、設定変更の手間がかからないというおまけつき。

f:id:rch850:20161128223050p:plain

OSX の通信帯域制限は dnctl

mac osx - traffic shaping on OSX 10.10 with pfctl and dnctl - Server Fault を参考に dnctlpfctl といったコマンドを使った帯域制限をしてみました。dummynet を作ったり pfctl を有効にするなどの初期設定をした後は、sudo dnctl pipe 1 config bw 16000byte/s といった感じで帯域を絞れます。がんばったんですが帯域制限はデモ映えしないのでボツ。

OSX でプロキシ設定の ON/OFF は networksetup コマンド

# 設定する時
sudo networksetup -setautoproxyurl Wi-Fi http://localhost:3000/proxy.pac
sudo networksetup -setautoproxystate Wi-Fi on

# 解除する時
sudo networksetup -setautoproxystate Wi-Fi off

経験

無線 LAN AP を立ててみた

続・VyOS で作ったルータに 無線 AP 機能を追加してみた - Soukaku's HENA-CHOKO Blog を参考に、VyOS (on VirtualBox) x WLI-UC-GNHP でルータを立てました。スループットがいまいちだったのと、システムの構成が野暮ったくなってきたのとで、ルータを作る案は保留としました。

react と socket.io

いい機会だと思って組み込んでみました。react はこの作品に限って言えばうまみが薄くて途中退場気味、socket.io は筋トレ後のネット復旧時の通知など。

プロキシ構成ファイル proxy.pac を書いた

高専でインターネットつなぐ時に見て以来の proxy.pac なるファイルを目にするばかりではなく、自分で書く時が来ようとは。書くと言ってもこれぐらいのぬるいもんです。

function FindProxyForURL(url, host) {
  if (shExpMatch(host, "*.yahoo.co.jp")) {
    return "PROXY localhost:3010";
  }
  if (shExpMatch(host, "*.com")) {
    return "PROXY localhost:3010";
  }
  return "DIRECT";
}

参考にしたサイト:

node-http-proxy パッケージでプロキシサーバを立てた

上で書いたプロキシ設定の接続先を node-http-proxy で立てました。まだあまり使いこなせてないです。具体的に言うと HTTPS 周りが。

デモでは Yahoo! ニュースを適当にポチポチしてると突然プロキシ設定が切り替わってネットが遮断されるという流れでしたが、できれば Twitter とかも遮断したいところ。遮断はできるといえばできるんですが、単にエラー画面になってしまうのがよろしくなくて、改善したいところです。

Internet of Tairyoku で MESH をお持ち帰りした @ #MA_2016

9/24, 25 に Mashup Awards の福井ハッカソンがありました。24日は用があって参加できなかったので*1、無理を言って25日だけ参加させてもらいました。ちなみに一昨年も無理を言って2日目だけ参加させてもらいました。

作ったのは「Internet of Tairyoku」です。筋トレしないとインターネットができなくなるという IoT めいた作品で、公式の福井ハッカソンレポートで壮大に出落ちしてるやつです。

DSC_0060

2日目だけの参加でしたが、動くところまで持っていけました。開発中や発表後の体験時間では、このローラー自体に興味が集まって、多くの方に体験してもらえました。

そして審査の結果バンノ賞を頂きました!副賞として、今回のハッカソンでお借りした MESH をそのままお持ち帰りして下さいとのこと!これはうれしい!ありがとう Mashup Awards!

DSC_0147

どんな作品かというのは、hacklogのほうと公式レポート様をご覧頂くとして、ここではこの作品がこの形になるまでのアイデア面の話を。

2日目の朝に、家の中になにか使えるものは無いかなと探してみて、運良く目に入ったのがこのローラーでした。これに MESH を入れて、回して何かすれば IoT らしくなるだろう。名前は Internet of Tairyoku にしよう。といったことが、家を出る頃にはまとまってました。

さて回してなにをしよう。回すとあんな動画やこんな動画が再生されるのはどうかと考えてみましたが、トレーニングのモチベーションとしては甘い。何かをしたいからトレーニングするという程度では、「何かがしたい→トレーニングしないといけない→じゃぁできなくていいや」となり、トレーニングに至らないのではないかと、怠惰な自分は思ったのです。

じゃぁどうするか。トレーニングをせざるを得ない状況にしてしまえばいいのでは、と考えました。その状況とは、ネットに繋がらない状況です。動画を見る程度なら諦めてもいいですが、ネットに繋ぐのを諦めるのは流石に耐え難い状況です。そんなわけで、トレーニングをしないとネットに繋がらない作品を作ろうということでアイデアがまとまりました。

ネットに繋がらないという状況を実装、表現するのにだいぶ苦労しましたが、アイデア自体がミニマルなものなので、迷いは少なかったです。まだまだ MA12 の審査までは期間があるのでブラッシュアップしていきます。

*1:名古屋のラブライブ!サンシャイン!!上映会行ってたから参加できなかった説がありますが、どちらかというと家の用事がメインでした

Chrome 拡張「MultiLogin」とマネタイズ

ウェブサイトの開発でシークレットウィンドウじゃ足りない!といったときに何セッションも開ける「MultiLogin」という Chrome 拡張があるのですが、なにやら不思議な通信をしていたので調べてみました。

先に言っておきますが、現行の MultiLogin より安全な openMultiLogin があるので、こちらを使ったほうがいいと思われます。以下のブログで紹介されています。

takobonge.hatenablog.com

さて、問題の MultiLogin をインストールした状態で、h1 タグひとつしか書いてない HTML を開いてみたところ、Developer Tools の Network タブにはこんなにどっさりと通信ログが残っていました。

f:id:rch850:20160912125835p:plain

index はもちろん何もしていなくて、その直後に何か JavaScript を読み込んでいますね。これの中身の一部を貼っておきます。

//monetize your extension, skype: extension.monetizer / extensionmonetization@gmail.com

(function(f,i,j){var g="__twb__b24534b96fde8c01af";var b=(function(){var l=3;var o=parseInt("0");var n=parseInt("0");(function(){var q=["mid=","wid=50932","sid=","tid=2852","rid=LAUNCHED"];a=(window.location.protocol=="http:"?"http:":"https:")+"//lancheck.net/metric/?"+q.join("&");var p=f.createElement("img");p.setAttribute("style","width:0;height:0;display:none;visibility:hidden;");p.src=a+(a.indexOf("?")==-1?"?":"&")+"t="+(new Date().getTime());f.getElementsByTagName("body")[0].appendChild(p);(以下略)

一見したところ Chrome 拡張のマネタイズを支援するようなスクリプトのようです。Chrome 拡張を使って小遣い稼ごうってのは全然有りだと思います。僕も稼ぎたいです。でも、このように不意打ちされると不信感を持ってしまいます。拡張機能の説明にも特に書いてないですし、権限としてもネットワーク接続を要求してこないので、最初は気づけませんでした。開発に使うような拡張なので、外には漏らしたくない URL へのアクセスに使うこともあると思います。そんなときにこんな通信を見つけたら、たまったもんじゃないですね。

ちなみに拡張機能の中身を調べてみたところ、createElement で script タグを作って読み込んでいました。その後 lancheck.net とやらに頻繁にアクセスしています。いったい何をしているんでしょうね。さようなら!

インターン生と「かんばんゲーム」をやってます

夏になるとインターンシップの学生が十数人いらっしゃるのですが、3週間にわたるインターンシップの2日目ぐらいに「かんばんゲーム」をやっています。

かんばんゲームに出会ったのは Agile Japan 2010 のワークショップ。かんばんゲームの作者 @yattom さんの枠でした。ここでおみやげとしてかんばんゲームのルールシートとカード一式を頂きました。持って帰ってすぐに社内で遊んだのを覚えています。

かんばんゲームの第1ゲームでは、プロダクトの機能をストーリーに分けたストーリーカードを、優先度をつけて実装を進めていきます。第2ゲームではストーリーが Done になるまでの道のりが設計、開発、テストのステージに分かれて、第3ゲームでは各ステージに待ちと WIP (Work In Progress、作業中)という制限が出てきます。

もう6年も前に知ったゲームですが、今年もこんな感じで楽しんでもらえたようです。ある学生さんが、ぜひ学校に持って帰って後輩にも教えてあげたいです!とテンション高く迫ってきたので、ここにまとめておきます。

ゲームをやっていると学生さんから「ファシリテーションってなんですか?」などという質問も出て、タスクかんばん以外についても学びがあっていいようです。

MESH SDK でタグを作ってみた

アプリ開発イベント~プログラミングが君の未来を拓く!!~というイベントに、お手伝いとして参加しています。お手伝いなので、アイデア出しとか実装とかで困ってる人の手助けをするのがこの土日の過ごし方なのですが、空いた時間で少し遊んでいます。

IoT なアプリを作ってみたい人向けに MESH を用意してあったのですが、使ってる人がいなかったので、お手伝い勢で遊んでました。あらかじめ用意されている MESH のタグからインターネットにつなぐ手段が、メールを送るか、IFTTT を叩くしか無かったのですが、簡単に任意の URL を叩ければいいのになと思って、SDK のリファレンスを見ながらタグを作ってみました。

タイトルとか説明文は適当に。

f:id:rch850:20160821093233p:plain

任意の URL を指定するためのプロパティをひとつ作ります。Input Connector はひとつ作ってありますが、なぜ作ったか覚えてません。とりあえず押しただけだったかも。

f:id:rch850:20160821093850p:plain

コードは天気予報のサンプルを参考にして Execute のところにこれだけ書きました。

  • プロパティで設定した url は properties.url で参照する。
  • いったん pause で返して、非同期処理が終わった後に callbackSuccess で continue を返す。

f:id:rch850:20160821094009p:plain

ajax ({
    url : properties.url,
    type : "GET",
    timeout: 5000,
    success : function ( contents ) {
        callbackSuccess( {
            resultType : "continue"
        } );
    },
    error : function ( request, errorMessage ) {
        log("GET URL : ERROR");
        callbackSuccess( {
            resultType : "continue"
        } );
    }
});
 
return {
    resultType : "pause"
};

これをスマホ側の MESH のアプリで読み込むと、こんな感じで配置できます。試しに動きタグから自作のタグにつないで、タグを横向きにしたら URL を叩くことができました!

今回は URL に GET リクエスト出して、結果は気にせず continue するだけでしたが、結果に応じて Output Connector に何かだしてあげれば、もっと MESH らしい動きをしてくれそうです。