最近はログを行指向の JSON として保存するケースが増えていると思います。
今どきは大体どの言語にも標準で JSON のライブラリが入っており、構造化データをログに残す手段として非常に手軽です。
Fluentd の in_tail で吸い上げるために JSON で残しているケースもあるでしょう。

そういった JSON ログをフィルタするツールとしては jq が有名だと思います。
私も日々使っています。

jq は非常に便利なのですが、複雑なフィルタをやろうと思うと、JavaScript 風の jq 独自のシンタックスでいろいろと書く必要があり面倒です。
特に、集計に reduce を使おうとした場合、どうやって書けばいいのかを思い出すのに時間がかかるので、ほとんど使いません。

これが Ruby で書ければ楽なのに…
ということで作りました。

jr: command-line JSON processor for Rubyists

GitHub: yuya-takeyama/jr

jr は JSON をフィルタ・集計するためのコマンドラインツールで、Ruby で記述できます。

実際にフィルタしたり集計したりする例は GitHub の README を参照してください。
GitHub API でリポジトリ一覧から必要な情報だけ抜き出したり、言語ごとにリポジトリ数を集計したりしています。

昼休みに思いついて、プロトタイプとして作った reduce-json というツールを元にしています。

JSON のストリームを Ruby で reduce するコマンド書いた

元々は reduce メソッドだけを実行できるものでしたが、せっかくだから map や find_all なんかもできた方がいいよね、ということで今の形になりました。

インストール方法

gem にしているので以下のようにインストールできます。

gem install jr-cli

jr の良いところ

jr は、jq がそうであるように、他のツールと組み合わせて使うことを目指しています。
UNIX 標準のツールと組み合わせるには、CSV 等の行指向のフォーマットに変換できる必要があって、それは未対応ですが、そのうちできればと思ってます。
jq と組み合わせることもできます。

とても便利なツールなので、是非日常の作業に使ってみてください。
欲しい機能などあれば、プルリクエストもお待ちしています。

,

はじめに

この記事は試験前日に部屋の模様替えをやりきったときみたいな気持ちで書かれています。

TL; DR

  • 買った音声教材のトラック分けが気に入らないので独自に切り分けたいが、量が多いと大変なので、インターネットのみんなと共同作業したい
  • 切り分けた音声ファイルをそのままアップロードすると著作権法上問題になってしまう
  • 「切り分け方」をコード化して GitHub で共有できるようにすればいいじゃない
  • それを実現するツール AudioHacker を Ruby で作った
  • サンプルとして DUO 3.0 / CD 基礎用を英文だけに切り取るための定義ファイルも作った

背景: TOEIC に初挑戦します

会社の同僚に誘われて、TOEIC 受けることにしました。
今回が初挑戦で、2014 年 3 月 16 日に行われる第 188 回を受験します。

どう勉強したもんかと思ったんですが、その同僚がこんな教材を薦めてくれました。

DUO 3.0 というのは英語の例文が 560 文掲載されていて、それをもとに重要な単語や熟語を覚えられるよ、みたいなヤツです。
語彙力が圧倒的に足りない私にとっては素晴らしい教材に思われます。
TOEIC 用に作られたものではありませんが、TOEIC 用としても十分実用的で、軽くググった限りではなかなか有名な教材のようです。

個人的には単語とか熟語だけを丸暗記するのは辛くて、むしろひとかたまりの例文の方が忘れにくいし応用もしやすい、と思ってます。
まぁ、大昔に読んだ「超」勉強法の受け売りなんですが。

そして、その DUO 3.0 の例文と訳文、さらにその中の単語・熟語の音読が聞けるのが DUO 3.0 / CD 基礎用です。

さっそく CD をリッピングして iPhone に入れてみたんですが、どうもトラック分けがイマイチ。
私としては 1 トラック 1 文に分かれていてほしいんですが、実際は 1 トラックに対して 2 文入ってたりします。
そしてそれらは前述の通り、英文、日本文、単語や熟語がごちゃ混ぜになってます。

これでは私がやりたい勉強法に使えません。

ぼくがかんがえたさいきょうの英文暗記法

  • 英文・日本文をそれぞれテキスト化
  • さらに英文の音声をひとまとめにする
  • 忘却曲線を考慮しつついい感じに問題を自動出題してくれるプログラムを用意する
  • 日本文に対して英文を暗唱
  • 必要に応じて音声を参考に発音も練習する

早い話が i暗記 + 音声ですね。
そういったプログラムについても今のところ私自身で実装することになってるんですが、いいのがあれば教えてください。

まずは音声データを用意

オリジナルデータとしてはもちろん DUO 3.0 / CD 基礎用を使うとして、それをいい感じに切り分ける必要があります。
しかし 560 もの例文となるとあまりの量に目眩がしてしまいます。
それを、インターネット上のみんなと協同作業することで解決しよう、というのは自然な発想です。

ですが、独自に切り取った音声ファイルを勝手にアップロードしたりすると、当然著作権法上問題となります。
そこで、CD は各自購入した上で用意して、その「切り取り方」だけを共有できればいいんじゃないか、と考えました。
「切り取り方」は Ruby の言語内 DSL としてコード化し、GitHub のリポジトリ上で共有できれば、プルリクエストによるコラボレーションも可能となります。

音声教材ハックツール、AudioHacker のご紹介

そこで作られたのがこの AudioHacker です。
AudioHacker は以下のような機能・特徴を持っています。

  • Ruby の言語内 DSL で記述した通りに音声ファイルを切り取る
  • 音声の切り取りには FFmpeg を利用 (なので使用可能ファイルは FFmpeg に依存)
  • 入力ファイルは iTunes 等でリッピングしたファイルの置かれたディレクトリを YAML ファイルで指定

単純に範囲指定で音声を切り出すだけなので、グリッチとかのアート的なヤツには使えません。

「切り取り方」を定義する DSL は以下のようなフォーマットです。

directory というのは、後に示す設定ファイル中の 1 番目のディレクトリから読み込むよ、という宣言です。
そして file はそのディレクトリ内で 1 番目のファイルを読み込むよ、という宣言。
なお、ここでいう「1 番目のファイル」というのは、ディレクトリ内のファイルを昇順でソートした順番を元にしています。
start は開始位置、duration は長さをそれぞれ秒で指定しています。
少数を使うこともできますし、文字列で 00:00:15.20 みたいなフォーマットで指定することもできます。
要は FFmpeg の -ss オプションや -t オプションに指定できるフォーマットが使えます。

そして設定ファイルは以下の通りです。
こちらは、利用者それぞれの環境によってディレクリ名もファイルフォーマットも異なるので、リポジトリ上では共有しないものです。

pattern というのは入力ファイルのファイルパターンを Ruby の Dir.glob で使えるフォーマットで指定します。
input_dir は入力ディレクトリのパスを指定します。
DUO 3.0 / CD 基礎用は 5 枚組なので、5 ディレクトリ指定しています。
なお、内部で利用している streamio-ffmpeg の制限上、ディレクトリ名もファイル名も ASCII にしておくのが無難です。
切り取られたファイルは output_dir で指定したディレクトリに書き出されます。

AudioHacker で DUO 3.0 / CD 基礎用を英文だけに切り取ろう

早速 DUO 3.0 / CD 基礎用を英文だけに切り取るための定義ファイルを用意しました。

DUO 3.0 / CD 基礎用 English Sentences for AudioHacker

…ただし、ひとりでは大変なのでまだ 10 文だけしか定義できてません。
Patches welcome ということで。

以下の手順で DUO 3.0 / CD 基礎用の切り取りが実行できます。

  1. DUO 3.0 / CD基礎用を用意する
  2. 適当なソフトで音声ファイルにリッピング (このとき、1 Disc 1 ディレクトリ、1 トラック 1 ファイルとし、ファイル名はソートできるよう先頭をトラック番号とすること)
  3. 以下の手順で AudioHacker を実行 (FFmpeg と Ruby 1.9 以上と Bundler 1.5 以上が必要)

FFmpeg は Mac を使っている人は brew install ffmpeg とかすれば入ると思います (各位頑張って入れてください)。

上手く行くと、以下のように出力されます。

AudioHacker を実行した様子

AudioHacker を実行した様子

設定ファイルに output_dir として設定したディレクトリにはファイルが出力されます。

AudioHacker が出力したファイル

AudioHacker が出力したファイル

終わりに

音声教材をハックしてコード化して共有するためのツール AudioHacker の紹介でした。

とりあえず Proof of Concept レベルの実装ではありますが、「GitHub 上でコラボレーションして音声教材をハックする」というアイディアは我ながらなかなか面白いんじゃないかと思ってます。
まぁ現状 Git や GitHub を当たり前に使えるエンジニアでないと使えないツールなので、このままでの普及は難しいとは思いますが…

さて、あとは自動出題用のプログラムを用意する必要がありますが、どう考えても TOEIC 受験時までに回収できない投資となりますし、とりあえずは本を読みながらアナログに勉強する予定だったりします。
続きはまたいつか。

, , , ,
Torutsume デモ

Torusume で赤入れっぽいことしてる様子

いわゆるウェブ系で働いていると、外向きに、それなりにしっかりした文書を書くことが日々あると思います。
メルマガだったり、プレスリリースだったり。
そういうのを社内で周囲の人間がレビューしてなおしたりとかあると思うんですが、あるときはメールやチャットでここはこうした方がよくない? とか言ったり、またあるときは紙に印刷して赤入れしたり。
まぁそういうのダルいと思う訳です。

そこであるとき、こういうの GitHub の Pull Request を使ったコードレビューみたいな感じにできると楽しいんじゃないか、って思ったのを、この正月休みを利用して作ってみました。

Torutsume: Git-based proofreading tool on the Web

ウェブサービスとしての公開ではなくて、あくまでデモサイトなので、ある日突然消えるかもしれません。
企業等、特定の組織内でプライベートな環境での使用を想定しているので、イントラとかに各自インストールして使う感じになってます。
ウェブサービスになってるとそれはそれで面白いと思うんですが、そうなるとプライベート投稿機能とか、組織を管理する機能とか必要になってくると思うのですが、そこまで作り込むモチベーションは今のところ無いのでした。

Torutsume の機能・特徴

  • 文書を投稿すると専用の Git リポジトリが作成される
  • 文書は、行ごとにコメントでツッコミを入れることができる
  • コメントのついた行が修正されると、コメントは非表示になる
  • Facebook 認証を利用して簡単にログインできる

とりあえず最小限の機能となってます。
コミットログで修正履歴とかも追えるといいと思いますが、とりあえず後回し。
あとは一度見えなくなったコメントを表示する手段もないので、その辺もなんとかしたいところです。

技術的な話

言語・フレームワーク・ライブラリ

Ruby 2.0.0 で Rails4 を使って実装しています。

ライブラリとしては FriendlyId とか Devise とか Omniauth とか Figaro とか。

この辺は去年作った Web アプリでも使ったんですが、ほとんど似たような実装を行ったので、ボイラープレートみたいなのを用意しておくと、便利何じゃないかと思っています。

CSS フレームワークには Twitter Bootstrap 3 を使っています。
Bootstrap は大変便利ですが、Rails に組み込むためのライブラリはいろいろあり過ぎてどれ使っていいのかわからないですね。
今回は bootstrap-sass-rails というのを使っています。
Devise や scaffold で生成されたフォームに Bootstrap を適用していくのに、地味に時間かかってます。

あとは開発用のものとしては rspec-rails とか guard-rspec とか pry-rails とか better_errors とか factory_girl_rails とか database_rewinder とか。
guard-rspec はいつのまにか spring に対応してたので、サクサク動いてよかったです。
CI では Travis CI と Coveralls 使ってます。

Git の操作

Git の操作には Rugged という libgit2 の Ruby バインディングを利用しています。
ライブラリを使うといっても、Git の操作を行うには Git の仕組み自体をそれなりに知っている必要があるので、作っていく段階でいろいろ勉強になってよかったです。
ディレクトリはツリーオブジェクトで、そこにファイルとしての blgb オブジェクトやサブディレクトリとして別のツリーオブジェクトがひもづいていて… とか。

リポジトリについては、プロジェクトディレクトリ内の repo ディレクトリ内にポコポコできます。
リモートの Git サーバを参照できるようにした方がいいとは思うものの、イントラでちょこっと使いたい程度なのでとりあえず手抜き。
時間あれば Gitlab あたりの実装を参考にしようと思います。

DI コンテナ

そして、各種ライブラリの利用には、先日リリースした dee-rails を使っています。
Git の複雑な操作を抽象化すべく、細かく階層化してモジュール (アプリケーションサービス) 化しているため、オブジェクトの生成はそれなりに複雑になっていたんですが、DI コンテナを通して利用する限りにおいては、そういった複雑性を忘れられました。
モジュールの実装は、とりあえず動けばいいやの適当なものになっていますが、テストもそれなりに書いてるので追々直していければという感じです。

作ってみて、やはり Ruby/Rails でも DI コンテナは便利だという印象です。
これが最良の方法かどうかはわかりませんが、まぁ悪くない感じにはなってます。
今までだと ApplicationController に以下のようなメソッドをいくつも実装していたのを、サービスプロバイダとして整理することができるようになっています。

# 今まで Rails でやっていた、サービス的なクラスの生成
class ApplicationController < ActionController::Base
  def some_benri_service
    @some_benri_service ||= SomeBenriService.new
  end
end

デモサイトのデプロイ

デモサイトはフロントに Nginx、App サーバに Unicorn という構成で、EC2 の micro インスタンス 1 台に載せてます。
DB は RDS で MySQL です。
プロビジョニング・デプロイには Chef Solo を使ってます。
相変わらず伊藤直也さんの本にお世話になりました。

Chef 便利ですが、新しい環境を構築するとなると、僕にとってはまだまだ一日仕事になってしまいます。
経験値の問題が大きいとは思いますが。
特定のバージョンの Ruby のインストールには ruby_buildrbenv のクックブックを使うのが便利でした。
Unicorn の実行にも既存のクックブックを使えればよかったんですが、rbenv で入れた Ruby を使う方法がよくわからなかったので、冪等性的には微妙な感じのクックブックを手書きで済ませてます。
MySQL のユーザやデータベースの作成には database クックブックが便利でした。

まとめ

文書校正支援 Web アプリ Torutsume を紹介しました。
そのうち社内用にインストールして使ってみつつ、モチベーション続く限り機能追加等していこうと思います。

, , ,