2013年6月4日火曜日

「現在の気温は23度です」を読み上げるまでのアレコレ

lindaで遊んでいます

linda-temperature-alertで温度をlinda-mac-sayに読み上げさせると数字21が“にい・いち”のようにひとつずつ読み上げられてしまい,“にじゅういちど”とかにならないのが悲しかった.

数字を漢数字にしてsaykanji記事(saykanjiコマンドを定義して漢字仮名混じり文を読み上げる - ザリガニが見ていた...。)のように'mecab -O yomi'すればいけるんじゃない?とか考えていろいろやりはじめた.その成果がこれ. 参考:漢数字に変換
n2k.rb
#! /usr/bin/env ruby -Ku
# coding: utf-8
def num2kanji(val)
  kanji_str= ':一二三四五六七八九'.split('')
  keta_str = ':十百千'.split('')
  keta_str2= ':万億兆京垓'.split('')
  return '零' if (val==0)
  val= val.to_s.reverse.gsub(/(\d{4})/, "\\1,").sub(/,$/, "").split(/,/)
  i= 0;
  for val_item in val
    str= ''
    chars= val_item.split('')
    j= chars.length-1
    for char_item in chars.reverse
      str+= kanji_str[char_item.to_i] + keta_str[j]
      j= j-1
    end
    str = str.gsub(/:./,'') + keta_str2[i]
    str= '' if (str.split(//u).length==1)
    val[i] = str.gsub(/:/,'');
    val[i] = val[i].gsub(/一(百)|一(十)/, "\\1\\2");
    i= i+1
  end
  return val.reverse.join('');
end
puts ARGV[0].gsub(/\d+/){ num2kanji($&.to_i) } if (ARGV[0] != nil)
でこれを
ruby n2k.rb 現在の気温は23度です|mecab -O yomi|say
と読み出せばいいんじゃないか?と思った. ただこれだと「気温は」の「は」が「ha」と発音されてしまう.
ruby n2k.rb 現在の気温は23度です|mecab -O yomi
ゲンザイノキオンハニジュウサンドデス
調べてみるとこれを解決されている方がいた. MeCab と KanateaTalk で漢字かな交じり文の読み上げ - 電脳スピーチ blog mecabをportsで入れたのでdicrcは/opt/local/lib/mecab/dic/ipadic-utf8/dicrcにあった. これに以下の三行を追加した.
node-format-talk = %pS%f[8]\s 
unk-format-talk = %M 
eos-format-talk  = \n
(ちなみにmecabで入れるとeucjpの辞書が入るので+utf8とかしていれないと色々困る) これで「は」は「wa」と発音されることになる
ruby n2k.rb 現在の気温は23度です|mecab -O talk
ゲンザイ  ノ  キオン  ワ  ニ  ジュー  サン  ド  デス  

で,ここまでやってフト,sayコマンドにKyokoさんがいたじゃないかと気がついた.

すっかり忘れてました.
(いまでもデフォルトでは使えなかったと思う.Kyokoさんのインストールについてはこちらの記事が参考になるかと思う.  「Kyoko」さんに優しく警告してもらう方法 - Macの手書き説明書)

ということで,以下のようにlinda-mac-say.rbを改造してみた.
(英語を読ませようとした時にKyokoさんだと冠詞「a」が「エイ」となったりするので全角があるときだけKyokoさんに登場いただくことにした.)
#!/usr/bin/env ruby
require 'rubygems'
require 'sinatra/rocketio/linda/client'
$stdout.sync = true

class String
  def sanitize
    self.gsub(/[`"'\r\n;\|><]/, '').strip
  end
end

url =   ENV["LINDA_BASE"]  || ARGV.shift || "http://localhost:5000"
space = ENV["LINDA_SPACE"] || "test"
puts "connecting.. #{url}"
linda = Sinatra::RocketIO::Linda::Client.new url
ts = linda.tuplespace[space]

linda.io.on :connect do  ## RocketIO's "connect" event
  puts "connect!! <#{linda.io.session}> (#{linda.io.type})"
  ts.watch ["say"] do |tuple|
    p tuple
    if tuple.size == 2 or (tuple.size == 3 and tuple[2].kind_of? Hash)
      str = tuple[1].sanitize
      opts = tuple[2] ? tuple[2].map{|k,v| "#{k} #{v}"}.join(' ').sanitize : ""
      vopt = (/[^ -~。-゚]/=~str)?"-v Kyoko -r 300":"-v Victoria -r 500"
      if system "say #{vopt} #{opts} \"#{str}\""
        ts.write ["say", str, "success"]  # write response
      else
        ts.write ["say", str, "fail"]  # write response
      end
    end
  end
end

linda.io.on :disconnect do
  puts "RocketIO disconnected.."
end

linda.wait

0 件のコメント: