NaCl非公式ブログ

NaClとの出会い

NaClの藤井です。
私は生まれも育ちも島根、Rubyが一般公開された1995年生まれです。
そんな私がどのようにしてプログラミングやRubyを知り、NaClに入ることになったのかをご紹介していきたいと思います。

...続きを読む

GhostTextプラグインの作成

NaClの前田です。

ブラウザ上でのテキストの編集は、カーソルを左に移動させようとCtrl+bを押したらMarkdownのマークアップが挿入されたり1、苦痛の多いものです。

テキストエディタでブラウザ上のテキストを編集できるGhostTextというブラウザ拡張がありますので、私の作っているTextbringerというテキストエディタ用のプラグインを作成してみました。

  1. 宗派に応じて「カーソルを左に移動させようとhを押したらhが挿入されたり」のように適宜読み替えてください。 

...続きを読む

小さなチームでの秘密情報の管理

こんにちは、東京支社の小田です。先週の週末は、やっと解禁されたHouse of Cardsのシーズン5をひたすらぶっ通しで見ていました。経験上、シーズンものは4や5までくるとマンネリ化しておもしろくなくなってくるんですが、House of Cardsは違いました。凄かったです。みなさんもぜひ。

簡単に説明すると、House of Cardsは組閣からもれ屈辱を味わった下院議員のフランクが、再度権力の階段を上がっていく政治ドラマです。人間は性欲なり金銭欲なり暖かい家庭を夢見たり、いろんな欲をバランスをとりながらもっていると思いますが、フランクは違います。フランクは権力(Power)だけ欲しそれのみを追求していきます。その徹底の程度が凄く(フランクはRuthless Pragmatismといっていますが)、敵だけではなく何人もの味方が特に良心をもっているほど、傷つき擦り切れ壊れていきます。どうですか?おもしろそうでしょ。

ちなみにNetflixで見る方は、Audio Descriptionが便利です。本当は視覚障害者の方用の音声モードですが、騙されたと思って試してみてください。

さて本題ですが、今日は小さなチームで秘密情報を管理する方法をご紹介します。管理に利用するツールは、PassというGnuPGとGitを利用したパスワードマネージャです。実行環境は、LinuxかmacOSを想定しています。

...続きを読む

ブラウザで撮影したカメラの画像をサーバに送信する方法

NaClの佐田です。

今回はブラウザで撮影したカメラの画像をサーバに送信するまでの記事です。 本記事を読まれた方が、カメラの簡単な操作をRailsアプリへ追加できるように紹介します。

本記事をご覧になっている方は、SNSを利用しているでしょうか。 私は携帯で撮影した画像をSNSにアップロードすることがあるので、仕事でカメラを撮影する機能をアプリに追加した時に面白いと感じたので記事にすることにしました。

確認した時の環境は「Chrome バージョン 56.0.2924.87 (64-bit)」です。 画像を撮影するカメラは、タブレット型パソコンにあるカメラ機能を使用しました。

サンプルをGitHubのsada/camera_appリポジトリに置いたので、そのコードを基に紹介していきます。

ブラウザからカメラを使用する許可

ブラウザからカメラを使用する方法は、WebRTC落穂拾い:初心者がつまずきやすいポイントをフォローの記事を参考にしました。 以下のようにカメラを使用するためのJavaScriptを書きました。

var stream;
var video;
navigator.mediaDevices.getUserMedia({video: true, audio: false}).then(function(stream) {
  stream = stream;
  video = document.getElementById('video');
  video.src = window.URL.createObjectURL(stream);
  video.play();
}).catch(function (error) {
  console.error('mediaDevice.getUserMedia() error:', error);
  return;
});

最初に、JavaScriptでカメラの使用許可を得るため、MediaDevices.getUserMedia()を呼び出します。 パソコンと接続しているカメラをブラウザで使用するには、使用許可がないと操作できません。 MediaDevices.getUserMedia()を呼び出すと、カメラの使用許可をブラウザが求めてきます。 URL先の記事では、chrome://flagsでフラグ設定をする必要があるとありましたが、確認した時のバージョンのChromeではフラグ設定をしなくてもカメラが動作しました。

また、カメラの機能自体が有効になっていないと使用許可を求めてきません。 私はVirtualBoxの仮想マシン上の環境で試しましたが、VirtualBoxの[メニュー]の[デバイス]の[Webカメラ]にある[Front Camera]と[Rear Camera]のどちらかが選択されて有効になっていないとカメラの機能が有効になりませんでした。

もちろんカメラの使用許可を求められた時に拒否するとカメラの映像を取得できません。

引数に指定しているvideoやaudioは、ユーザのカメラやマイクへの使用許可を求めるためのオプションの指定です。 MediaDevices.getUserMedia()の戻り値としてPromiseが返されます。 もしカメラの使用が許可された場合は、then関数内でカメラの映像をvideoタグに読み込ませて再生されます。 もしカメラの使用が拒否された場合は、catch関数内の処理が実行されてブラウザのコンソール上にメッセージが表示されます。

カメラの映像を画像データに変換

カメラの映像を表示することができました。 カメラの映像を画像データに変換するには、canvasにカメラの映像を渡してからHTMLCanvasElement.toBlob()を呼び出してBlobオブジェクトにします。

var stream;
var video;
navigator.mediaDevices.getUserMedia({video: true, audio: false}).then(function (stream) {
  stream = stream;
  video = document.getElementById('video');
  video.src = window.URL.createObjectURL(stream);
  video.play();
  setTimeout(function() {
    var canvas = document.getElementById('canvas');
    var ctx = canvas.getContext('2d');
    var w = video.offsetWidth;
    var h = video.offsetHeight;
    canvas.setAttribute('width', w);
    canvas.setAttribute('height', h);
    ctx.drawImage(video, 0, 0, w, h);
    canvas.toBlob(function(blob) {
      var img = document.getElementById('image');
      img.src = window.URL.createObjectURL(blob);
    }, 'image/jpeg', 0.95);
    stream.getTracks()[0].stop();
  }, 3000);
}).catch(function (error) {
  console.error('mediaDevice.getUserMedia() error:', error);
  return;
});

setTimeoutを使用して、3秒後にHTMLCanvasElement.toBlob()でカメラの映像をJPEG形式に変換してからimgタグに渡しています。 setTimeoutでカメラの映像の変換を遅らせるのは、そうしないと、カメラの映像が表示される前の黒い画像で画像データとして表示されてしまうからです。

上記までのJavaScriptでは、カメラのサイズを指定していないので、デフォルトのサイズで表示されています。 カメラのサイズを変更するには、以下のようなオプションを指定します。

var constraints = {
  video: {
    mandatory: {
      maxWidth: 320,
      maxHeight: 240
    }
  },
  audio: false
};
navigator.mediaDevices.getUserMedia(constraints).then(function (stream) {
  // 省略
});

上記のオプションの指定によって、カメラのデフォルトのサイズが640x480で表示されていたのが320x240のサイズに変更されました。 maxWidthとmaxHeightは、カメラの縦横の幅の最大を指定しています。 オプションで指定した値に近い、使用できるカメラのサイズの規格に変更されています。

画像の保存

ここまでカメラの映像を画像データに変換して表示することを紹介しました。 次に、Railsで立ち上げたサーバに送信してデータベースに画像データを保存します。

先ほどはimgタグのsrc属性に渡していたBlobオブジェクトをFormDataに渡してRailsサーバに送信します。

navigator.mediaDevices.getUserMedia(constraints).then(function (stream) {
  stream = stream;
  video = document.getElementById('video');
  video.src = window.URL.createObjectURL(stream);
  video.play();
  setTimeout(function() {
    var canvas = document.getElementById('canvas');
    var ctx = canvas.getContext('2d');
    var w = video.offsetWidth;
    var h = video.offsetHeight;
    canvas.setAttribute('width', w);
    canvas.setAttribute('height', h);
    ctx.drawImage(video, 0, 0, w, h);
    canvas.toBlob(function(blob) {
      var img = document.getElementById('image');
      img.src = window.URL.createObjectURL(blob);

      var request = new XMLHttpRequest();
      request.open('POST', '/avatars');
      request.setRequestHeader('X-CSRF-Token', $('meta[name="csrf-token"]').attr('content'));
      var formData = new FormData();
      formData.append('avatar[image]', blob, '<%= Time.now.strftime("%Y%m%d%H%M") %>}.jpeg');
      formData.append('avatar[uuid]', '<%= user.uuid %>');
      request.send(formData);
    }, 'image/jpeg', 0.95);
    stream.getTracks()[0].stop();
  }, 3000);
}).catch(function (error) {
  console.error('mediaDevice.getUserMedia() error:', error);
  return;
});

サンプルのRailsアプリでは、画像を保存するgemパッケージとしてpaperclipを使用しました。

外部への公開について

本記事ではbundle exec rails serverコマンドでサンプルのサーバを立ち上げることを想定しています。

もし外部に公開する場合、ChromeはMediaDevices.getUserMedia()を使用しているならばhttpsに設定しないといけません。 Deprecating Powerful Features on Insecure Originsにて書かれています。

まとめ

MediaDevices.getUserMedia()を使用したカメラの画像を撮影することについて書きました。

参考情報

WebRTC落穂拾い:初心者がつまずきやすいポイントをフォロー

camera_new.html

MediaDevices.getUserMedia()

HTMLCanvasElement.toBlob()

Resolution Constraints in Web Real Time Communications draft-alvestrand-constraints-resolution-00

paperclip

Deprecating Powerful Features on Insecure Origins

お仕事駆動でパッチを送ってコードコントリビュート!

NaClの中村です。

OSSに関するイベントの会場などでたまに「OSSにコードコントリビュートしたいんですけどなかなかできなくて…」と聞くことがあります。 私も含め、OSSのイベントに参加されるような方は単にOSSを利用するだけでなく、コードコントリビュートしたい人が多いようです。 確かに自分が書いたコードが広く普及しているOSSに入り、いろんなところで動くのは気持ちのよいものです。

しかし、我々プログラマは日頃のお仕事もあるし、家に帰れば猫の世話に追われ、見たいアニメもある。 ツイッターでは「すごーい!」とつぶやきたいし、とても多忙な日々を過ごしています。 パッチを書いている暇はないのです。

そこでお仕事の時間を利用してパッチを書いてみようというのが今回の趣旨です。 この記事では私が実際にお仕事をしつつパッチを書いた例を見つつ、どのようにOSSにコードコントリビュートするのか紹介したいと思います。

動かないコードの発見

お仕事で以下のような状況がありました。

プロキシ環境

...続きを読む

インターンシップに参加して

はじめまして、2/20 から2週間インターンシップでNaClさんでお世話になってる吉岡です。
普段は神戸にある専門学校に通っているのですがなぜ島根県松江市にあるNaClさんのインターンシップに参加したのかというと

  1. 地元が松江市だったから
  2. Rubyを使ってのお仕事をしている

の2つが主な理由だったりします。

...続きを読む

WebAPIによる周辺施設検索

NaClの石飛です。

全国の様々な場所にライブを見に行くことが趣味です。 そんな時会場までの道順などは調べるのですが周辺の施設についてはあまり調べず、いざ会場まで行ってみるとコンビニがすぐ近くになくて困ることなどもあります。 そこで施設名を渡すと周辺施設の件数や名前をWebAPI呼び出しを通して返してくれるスクリプトを書いてみたので紹介します。

...続きを読む

コマンドによるクリップボードの活用

NaClの野口です。

まず本記事内のクリップボードとはコピー、ペーストをする際に使用する一時領域のことを指します。

端末エミュレータ上での作業の際、クリップボードへ保存(コピー)する領域の選択にマウスを使用することがありますが、以下のような不満を私は感じています。

  • 意図した領域の選択を行うことが難しい
    • 選択領域に過不足があった場合の微調整が難しい
    • 疲れている時には特に難しく、またこの作業を行うことで疲労が更にたまる
  • 繰り返し作業が苦痛
    • 複数行のコピー、ペーストを複数回行う作業は考えるだけで嫌
    • マウス操作は自動化しづらいため楽が出来ない

上記のことを踏まえてマウスを極力使用せず、コマンドを使用してクリップボードを活用する方法について記載します。
また本記事はマウスに触れる時間を極力減らし、キーボードのみでクリップボードの操作を行うことを目標とします。

...続きを読む

Windows上でRuby初心者向け学習環境を作る

NaClの野坂です。

普段は松江市にある本社オフィスで、主にRubyを使ったシステム開発をしつつ、時々Ruby関連のセミナー講師なども務めています。 また、週末は地元のサッカーチームを応援するサポーター活動などしています。

サッカー大好きな私としては、いつか松江市が「サッカーの街」として有名になってくれたらいいなぁ、などと密かに念じていたり しますが、やっぱり業界的には「Rubyの街」という印象が圧倒的かと思います。 実際、地元のクラブの試合を応援していても、ハーフタイムの雑談中に、IT業界とは無縁なはずのサポーター仲間から、

「Rubyってヤツを勉強しようと思ったら、どう始めればいいの?」

なんて普通に聞かれたりする街です。

本稿では、そんなRuby初心者に実際にRubyが実行できる環境を提供する方法についてご紹介したいと思います。

...続きを読む

Amazon S3上のファイルをX-Sendfileで配信する

NaClの田中です。

Amazon S3に格納したファイルを、X-Sendfileを使って配信する仕組みを構築しました。この記事ではその実現方法を紹介します。

X-Sendfileとは?

X-Sendfileとは、NGINXのドキュメントによると「認証、ロギングなどをバックエンドで処理した後、内部リダイレクトされた場所からエンドユーザにコンテンツを配信するようにWebサーバが処理することで、バックエンドを解放して他の要求を処理させる仕組み」だそうです。Webサーバにコンテンツ配信をさせ、バックエンドのスループットを向上させるための機能、ということですね。
詳しい利用方法についてはドキュメントを参照ください。

AmazonS3上のファイル配信

さて本題です。今回やりたかったことはAmazonS3上にあるファイルの配信です。

...続きを読む