音声認識システム Julius を使って twitter に投稿する ruby スクリプト
最近、急に自分の周辺で非技術者の人から twitter の話題を聞くことが多くなりました。うーんツイッター流行ってきてるんだなー、じゃなんかネタスクリプトでも書いてみよっかな、、、と30秒ほど考えて「リアルにつぶやいた内容を音声認識してツイッターにポストするか」と思いつきました。
が、しかし、誰でも思いつくことは同じで、あちこちで似たような事をしている人がいたので、やっぱやめるかと思ったものの、クリスマスで暇だし、Mac OSX上でやってる人は見つけられないしで、勢いで音声入力システムの Julius を利用したツイッター投稿スクリプト書いてみました。ちなみに環境は、Mac OSX 10.5.8 + ruby 1.8.7 です。
音声認識システム Julius のインストール
まず Julius の cvs から最新のソースをダウンロードしてコンパイル&インストールします。インストール先は、prefixで適当に好きなところに設定してください。
% cvs -z3 -d:pserver:anonymous@cvs.sourceforge.jp:/cvsroot/julius co julius4 % cd julius4 % ./configure --prefix=$HOME/bin % make % make install
次に Julius のホームページから Linux版 Juliusディクテーション実行キット v4.0 をダウンロードし、適当なフォルダに展開します。ここでは、~/local/dictation-kit-v4.0 に展開しました。
Julius の起動テスト
展開したフォルダにある設定ファイル(fast.jconf) を -C オプションで指定して、以下のように Julius を起動します。
julius -C ~/local/dictation-kit-v4.0/fast.jconf -charconv EUC-JP UTF-8
すると、起動ログが表示されたあとに
<<< please speak >>>
ってでますんでマイクに向かって「こんにちは!」ってしゃべると
pass1_best: 今日 は 、 sentence1: こんにちは 。
こんな感じ↑で音声認識されます。
ruby から Julius を使う
Julius とアプリケーションを連携させるにはいくつか方法があるんですが、Julius をモジュールモードで起動するのがお手軽そうなのでこの方法を使います。
先程 cvs からダウンロードしたソースコードの中に、モジュールモードで起動した Julius をperl から利用するサンプルスクリプト(jclient-perl)があったので、これを参考に ruby で書きなおして twitter 投稿処理などなどを追加しました。
まず、Julius をモジュールモード(-module)で起動します。
julius -C ~/local/dictation-kit-v4.0/fast.jconf -charconv EUC-JP UTF-8 -module
gem install nokogiri twitter してから、以下のソースを動かします。
#! /usr/bin/env ruby # -*- coding: utf-8 -*- require "socket" require "rubygems" require "nokogiri" require "twitter" TWITTER_ID = "your twitter id" PASSWORD = "your twitter password" def twit(s) auth = Twitter::HTTPAuth.new(TWITTER_ID, PASSWORD) agent = Twitter::Base.new(auth) agent.update(s) end s = nil until s begin s = TCPSocket.open("localhost", 10500) rescue STDERR.puts "Julius に接続失敗しました\n再接続を試みます" sleep 10 retry end end puts "Julius に接続しました" source = "" while true ret = IO::select([s]) ret[0].each do |sock| source += sock.recv(65535) if source[-2..source.size] == ".\n" source.gsub!(/\.\n/, "") xml = Nokogiri(source) words = (xml/"RECOGOUT"/"SHYPO"/"WHYPO").inject("") {|ws, w| ws + w["WORD"] } unless words == "" twit(words) puts "「#{words}」を twitしました。" end source = "" end end end