2018年4月22日日曜日

MMOのチャットログを翻訳→読み上げる

MMO全盛期にできてればよかったのになぁ

8年以上前に海外のMMOを(英語がまったくもってできない)のにやっていたころ、
チャットログを翻訳できれば便利なのになぁと思ってなんとかできないかちょっと検討してみたのですが、
ゲーム側が記録続けているテキストファイルに対して最新の行を取得する方法がいまいちわからなかったのですよね。

時が立ちいろいろやってくうちに少し解決しました(C++ですけど)
対象のテキストファイルが更新されても一度EOFに到達している後は新しい行が取得できない
原因はEOFを一度見つけるとEOFを見つけたフラグが立つから。
それでfgetsで続きがよめなくなるので、このフラグをクリアする(ifs.clear()。)
このころは英語のMMOを既にやってないので翻訳は気にしなかったし、C++でAPI投げる方法も全然わからなかった。

今はPHPでYouTube Data APIを投げるのは慣れてきたので、できるじゃんということでやってみました。
PHPではifs.clear()みたいなのが見当たらないので
fseek($fp, ftell($fp))で確認した行まで再度シークすることによって
EOFのチェックを再び行うことによって実現しています。
この更新され続けるテキストを監視する方法がネットで検索しても出てこなかったから苦労した。
需要はありそうだし、他にエレガントのやり方があるのだろうか?

翻訳の部分はYouTube Data APIと同じノリで 「Google Cloud Translation API」を使います。
ただし、これは有料の機能です。
Google Play Consoleで300ドル分のクレジット期限付きであったのでこれを活用。(お試し用?)
20ドル/100万文字(全部マルチバイト文字だとたら200万バイト→1.9MB相当?)だそうですが10万文字で10ドルなど使った分だけ請求されるみたい。
Google Play Consoleの方でYouTube Data APIと同じように「Google Cloud Translation API」を有効にします。
既存のAPIキーがあればそれで「Google Cloud Translation API」が使用できます。
課金されるのでAPIキーが他人に漏れないように!


ついでにYouTubeの方もチャットも読み上げソフトで読めたらなぁと思い練習用に
翻訳後の結果を有名なソフト「棒読みちゃん」に読み上げさせます。
これは「棒読みちゃん」のフォルダの下にある「RemoteTalk.exe」にメッセージを投げればよいです。


以下、今回のコードの仕様
・PHPファイルと同じフォルダにあるtest.txtを対象とします。
・PHP実行後にtest.txtに追加された行を対象とします
・英語→日本語の翻訳を行います。(もともと日本語の場合もAPIへ投げているので課金されると思います。)
・翻訳結果を棒読みちゃんで読み上げを行います。
・ゲームチャットのログとして実行例として自分が昔やっていたMMO(サービス終了済み)を使用します
使用したゲームのログにあわせてメッセージ部分を取り出してください。
・自分の発言はロボット、それ以外は女性1の声質を使います

テスト用txtファイル例 これを上から5行目に1行ずつ足して保存すれば翻訳されたものが読み上げられます。
TEST.txt
1
2
3
4
2024/12/01 21:34:10 :>パーティー< :Let's attack from the back of the enemy
2024/12/01 21:39:21 :<パーティー> Okayu :用意ができたら
2024/12/01 21:39:27 :<パーティー> Okayu :When ready
2024/12/01 21:39:09 :>パーティー< :Then please tell me if you can



以下がコードとなります。①は自分のAPIキー。②は自分のフォルダ位置に合わせてください。
使用する前に棒読みちゃんを起動した状態で行ってください
ReadChat.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
<?php
define("APIKEY","①");
 
//翻訳関数
function trns_us($text)
{
 $url = "https://www.googleapis.com/language/translate/v2?key=" . APIKEY . "&source=en&target=ja&q=".urlencode($text);
 $resjson = file_get_contents($url);
 $resjson = mb_convert_encoding($resjson, 'UTF-8', 'auto');
 $resarray = json_decode($resjson);
 $result = $resarray->data->translations[0]->translatedText;
// echo $result;
 return $result;
}
 
//RemoteTalkへのパス
$toolpath="C:\\Users\\HogeHoge\\Documents\\tool\\BouyomiChan\\RemoteTalk\\RemoteTalk.exe /T ";//←②
 
define("TESTFILE","./TEST.txt");
 
$fp = fopen(TESTFILE, "r");
fseek( $fp, 0, SEEK_END);//最後の行へ移動
 
while(1)
{
 while ( $line = fgets($fp) )
 {
//  echo $line;
 
  //フォーマットに合わせて分解する
   $data=explode(":",$line);
  $str = $data[1];
 
  $data1=explode(" ",$data[0]);
  if(count($data1) == 5)
  {
   $name = $data1[3];
   $voice = " -1 -1 -1 1";//女性1
  }
  else
  {
   $name = "自分";
   $voice = " -1 -1 -1 6";//ロボット
  }
 
  //echo $name . PHP_EOL;//キャラ
   //echo $str . PHP_EOL;//テキストデータ
   
  $str = trns_us($str);//翻訳
   
  //棒読みちゃんに飛ばす
  $tmp_cmd = $toolpath ."\"". $str."\"".$voice;
  $ftolk =  popen($tmp_cmd,'r');
  pclose($ftolk);
 
  //配列のクリア
  unset($data);
  unset($data1);
 }
 usleep(1*1000000);//1秒待ち
 fseek($fp, ftell($fp));//再チェック
}
 fclose($fp);
 
?>



注釈として
//echoはデバッグ用です。
17行目は自分のフォルダに合わせてください。\\は2つずつ書くようにしてください。
31行から44行目は自分のゲームのフォーマットに合わせ。声の割り当ても自分の趣味で。
7行目。URLに翻訳した文とAPIキー。翻訳元言語、翻訳先言語を指定して投げると
JSONでレスポンスが返ってくるので結果を取り出すだけ
日本語だろうとかまわずAPIに投げます。
49行目 ここコメントアウトで翻訳なしに。
52行目。スペースが入ったりするとアレなので””で囲む。
53行目と54行目。PHPからのアプリ実行はいくつも方法があるのでよくわからないけど、
これでよさそう。
63行目。ここには到達しません。


改善点として
対象ファイルはドラッグとかで指定できるようにしたほうがいい
<ささやき>や<シャウト>で音量を変えたり、特定の人に特定の声質を当てるなど自分で好きなようにコーディングして調整してみたください。
エラーチャックはしてません。いつも通り動けばいいで雑です。
ファイルの行が減ったりすると暴走しそう。
YouTubeのチャットも同じように投げたり翻訳できたり自分用にカスタマイズできますね。
正規表現でチャットログのメッセージを分解した方がエレガントかも。


昔できなかったことができるってのは成長です!
次の機会まで 「Google Cloud Translation API」は無効にして封印!

0 件のコメント:

コメントを投稿