Hatena::ブログ(Diary)

サイト更新停滞ちうっ このページをアンテナに追加 RSSフィード

2017-05-10

動画作成用の音声再生アプリと、ライブ放送読み上げ用の音声再生アプリでは要件が違う話 21:13  動画作成用の音声再生アプリと、ライブ放送読み上げ用の音声再生アプリでは要件が違う話を含むブックマーク  動画作成用の音声再生アプリと、ライブ放送読み上げ用の音声再生アプリでは要件が違う話のブックマークコメント

動画に再生する音声メッセージでキモいボイスを流さなくても済むように、

指定されたメッセージを読み上げるアプリを作成した。機械音声なら美声でなくても安心である。


さて、昨今、こういった機械音声はライブ放送や実況などでも利用されているが、

動画作成用に作った音声再生アプリをライブ放送のコメント読み上げに使おうとしても、

そのままではうまくいかない。


ちょっと試してみたところ、

動画作成用の音声再生アプリと、ライブ放送のコメント読み上げアプリでは、

どちらも似たような音声再生のアプリでありながら、アプリの要件が違っていたのです。


どんな要件の違いが?

・動画作成用の音声再生アプリは、動画の制作者の指定どおり忠実に音声を再生することが期待されている。

・ライブ放送のコメント読み上げアプリは、一部のメッセージをライブ放送用に読み替える機能が期待されている。

w → ワラワラ


・ライブ放送では動画の運営コマンドが飛んでくる。これは読み上げてはいけない

・動画作成用ではそのまま読み上げて欲しい。読めない語があっては困る。

/hidden

@コテハン


・並列で多数同時にメッセージが飛んでくる。

ライブ放送では、これらをキューにいれて順番に読み上げてあげる必要がある。

(試しに書かれたそばから再生してみたら凄かった。まるで動物園のようだった。)


・たとえば、辞書機能があるとして、動画作成用と、ライブ放送用では、辞書に入れるデータがだいぶ違ってくる。

・動画作成用では、頻出ワードとか辞書に登録する

・ライブ放送用では、こう読んで欲しい、みたいな語を辞書に登録する

・この2つの辞書は絶対共有できないですよね


設計的な話で言うと

ライブ放送用の音声再生アプリでは、音声再生のキューの処理機能と、一部音声のフィルター機能が要るが、

動画再生用の音声再生アプリには不要。

ライブ放送用、動画再生用で作りを変えるのは、嬉しくない。


ライブ放送用のアプリと、動画再生用の音声再生アプリを一緒にすると、

結構面倒なことになってしまいますね。


ところがギッチョン

棒読みちゃんなどのメジャーな音声アプリは、その辺、一つのアプリで両方に対応していて、

あ、ご苦労様です、苦労してたんですね、という感じなのでありました。

2017-03-16

[][][] Web Audio APIで作ったaudio/wav形式の音声を保存する 01:01  Web Audio APIで作ったaudio/wav形式の音声を保存するを含むブックマーク  Web Audio APIで作ったaudio/wav形式の音声を保存するのブックマークコメント

この(↓)のアプリを作っている間に得た知見

https://github.com/taku-o/myukkurivoice

D


Web Audio APIで作った音声を保存する方法は、調べると色々出てくるのですが、

  • Recorder.js
  • MediaStream Recording API
  • ScriptProcessorNode

この記事では、自分にはこれが簡単そうだなと思った方法を書きます。


node wave-recorder を使う

node wave-recorder

https://www.npmjs.com/package/wave-recorder


このライブラリを使うと、おおよそこんな感じのコード(↓)で、Web Audio APIで加工した音声データをファイルに保存できます。

YATTAZE簡単!!

少なくとも他の方法よりは。そう見える。

var fs = require('fs');

function to_array_buffer(buf_wav) {
  var a_buffer = new ArrayBuffer(buf_wav.length);
  var view = new Uint8Array(a_buffer);
  for (var i = 0; i < buf_wav.length; ++i) {
    view[i] = buf_wav[i];
  }
  return a_buffer;
};

var a_buffer = to_array_buffer(buf_wav);

var audioCtx = new window.AudioContext();
audioCtx.decodeAudioData(a_buffer).then(
  function(decodedData) {
    // source
    var sourceNode = audioCtx.createBufferSource();
    sourceNode.buffer = decodedData;
    sourceNode.onended = function() {
      recorder.end();                                    // ここでend()しないと超巨大なファイルが出来る
    };

    // gain
    var gainNode = audioCtx.createGain();
    gainNode.gain.value = volume;

    // recorder
    var recorder = WaveRecorder(audioCtx, {              // ← recorder作って
      channels: 1,                                       // ←
      bitDepth: 16                                       // ←
    });                                                  // ←
    recorder.pipe(fs.createWriteStream(wav_file_path));  // ←

    // connect and start
    sourceNode.connect(gainNode);
    gainNode.connect(recorder.input);                    // ← 繋げる
    sourceNode.start(0);
});

でも、なんか作った音声ファイルの最後の方が切れるんだけど

ただし、良いことだけでなく、node wave-recorderを試してみると問題も見つかったのです。

作成した音声ファイルの、最後の方がファイルに保存されないのです。

(自分の技量の問題もあるでしょう)


# 音声
こんにちわ

# ファイルに保存された状態 (最後の方が欠ける)
こんにちw

下のコードで、音声データの加工が終わった時にファイルへの書き出しを閉じているのですが、

onendedイベントのタイミングでは、ストリームを閉じるのが少し早かったりするのでしょう。

// source
var sourceNode = audioCtx.createBufferSource();
sourceNode.buffer = decodedData;
sourceNode.onended = function() {
  recorder.end();
};

なお、これを見て、自分が取った解決策が↓である。

// source
var sourceNode = audioCtx.createBufferSource();
sourceNode.buffer = decodedData;
sourceNode.onended = function() {
  // onendedのタイミングでは出力が終わっていない
  setTimeout(function(){
    recorder.end();
  }, 100);
};

汚い!!

でも、事件は現場で起きているんだ!!

(これは、時間があるときに解決を試みることにする)


おまけ。node-wav

node-wav

https://www.npmjs.com/package/node-wav


このようなライブラリも見つけた。wave-recorderから呼び出されていた。

このライブラリはWeb Audio APIで作った音を保存するものではない。


が、ストリームをファイルに保存する機能がある。

audio/wav形式のファイルのヘッダとか、フォーマットとか、その辺の処理をやってくれる。

加工した音声をストリームの形式に持っていけるなら、便利に扱えそうです。

良さそうだったが、今回は使用しなかった。


READMEにはその辺の機能の説明は載っていないが、

落としてみて、lib/file-writer.js とか読むと幸せになれそう。


おわり

最終的には、MediaStream Recording API に移行したい。

2017-01-16

[][] Mac Sierraでも動作するAquesTalkの音声再生アプリMYukkuriVoiceを作った 20:56  Mac Sierraでも動作するAquesTalkの音声再生アプリMYukkuriVoiceを作ったを含むブックマーク  Mac Sierraでも動作するAquesTalkの音声再生アプリMYukkuriVoiceを作ったのブックマークコメント

アプリ説明は動画の中で説明しているので、この記事では、このアプリを作った時に得られた

(役に立たない部分が多そうな)知見について話そうと思う。

https://github.com/taku-o/myukkurivoice

D

Macのゆっくり事情

いわゆるゆっくりの声はAquesTalkというライブラリで作るのだけど、この声を出すアプリは、

などがある。


Mac環境唯一のアプリゆっくろいどMac Sierraで動作しなくなったのが、

今回のアプリの作成の経緯ですね。


AquesTalk

この系統のアプリの仕組み

AquesTalk(http://www.a-quest.com)のライブラリには、

があり、

この2つの機能を利用して声を再生および保存するのが、この手のアプリの基本的な仕組みです。

日本語のメッセージ
  ↓
  ↓ AqKanji2Koe
  ↓
音声記号列
  ↓
  ↓ AquesTalkWAVバイナリ

AquesTalkライセンス

AquesTalkライブラリには

がある。

これらのライセンスは AQUEST Online Store(http://shop.a-quest.com/?mode=cate&cbid=1377248&csid=0)で購入する。


よって、商売などで作成したアプリを配布するには頒布ライセンスが必要なのだが、

広く公開するアプリ個人利用における無償配布規定に従える場合は、

個人利用ライセンスを利用できる(審査あり)。


Node.js + Native

ということで、

アプリの機能を実現するには、Node.jsからダイナミックライブラリを呼び出す方法が必要になった。


Node.jsからNativeの機能を呼び出す方法は、調べると、

などがあった。


3番目のSWIGは色々な言語からの呼び出しに対応していて、一見凄そうだが、

冷静に考えると使う側からすると、必要な言語から呼び出せれば、それで良いかな、という気がしないでもない。


一番下のemscriptenはよく調べていないけれど、

Node ffiSWIGは、最終的にはNode.jsネイティブ拡張と同じことをしているっぽい?

(深く追いませんけど)


今回はNode ffiを利用しましたが、結構安定している印象。

Node ffiの使い方の例は、大体このような感じ

var ffi = require('ffi');
var ref = require('ref');

var ptr_uchar = ref.refType(ref.types.uchar);
var ptr_int   = ref.refType(ref.types.int);
var ptr_void  = ref.refType(ref.types.void);

// unsigned char * AquesTalk2_Synthe_Utf8(const char *koe, int iSpeed, int * size, void *phontDat)
var framework_path = 'AquesTalk2.framework/Versions/A/AquesTalk2';
var ptr_AquesTalk2_Synthe_Utf8 = ffi.DynamicLibrary(framework_path).get('AquesTalk2_Synthe_Utf8');
var fn_AquesTalk2_Synthe_Utf8  = ffi.ForeignFunction(ptr_AquesTalk2_Synthe_Utf8, ptr_uchar, [ 'string', 'int', ptr_int, ptr_void ]);

var alloc_int = ref.alloc('int');
var encoded = '';
var speed = 100;
var phont_data = ....;
var r = fn_AquesTalk2_Synthe_Utf8(encoded, speed, alloc_int, phont_data);
var buf_wav = ref.reinterpret(r, alloc_int.deref(), 0);

動画

動画作成者向けのアプリなので、その層の人に情報を伝えるには、動画を作る必要がある。たぶん。

ボイスロイド

この動画はボイスロイドを解説者として採用している。

(おっさんの声より良いという判断。だが、実際、ミス無く喋るのは難しい、ので手間はあまり変わらないのだ)


ボイスロイドの会話は、ゆっくり系の声より会話の速度が速い。同じ会話を話させても短い時間で終わる。

ゆっくりに同じ早さで話させると、早口に聞こえがちなようだ。


解説者として使いやすいボイスロイドは、自分の主観では、

結月ゆかりの方が使いやすい。

たまに苦手な台詞、言い回しがあり、その場合は、台詞を変えて回避すると良い。


逆に使いにくそうなのは、

調音が少し難しいのと、関西弁の発音にされちゃうのが理由。


会話のリズム

動画の会話の間をうまく制御できない人は、セリフの合間を作らずにひたすら喋らせまくれば、

センスが無い人でもそれなりに誤魔化せる、という動画作成者的ノウハウがあるらしい。

(1秒以上、会話していない時間を作らないようにする)


実際、このノウハウは効果的だと思う。


2人以上話す人が居ると、切れ間のない会話を作りやすい。


おわり

未知の作業が多かったので、いろいろ勉強になった

2013-12-08

vagrant + debian + plone 14:40  vagrant + debian + ploneを含むブックマーク  vagrant + debian + ploneのブックマークコメント

install vagrant

  • 省略

install Debian

cd /usr/local/src/vagrant
vagrant box add debsqueeze64 http://www.emken.biz/vagrant-boxes/debsqueeze64.box
vagrant box list
vagrant init

edit Vagrantfile

  • 運用スタイルに合わせて適当に
- config.vm.box = "base"
+ #config.vm.box = "base"
+ config.vm.box = "debsqueeze64"
- #config.vm.network :public_network
+ config.vm.network :public_network
  • 動作確認
# 起動/停止/ssh
vagrant up
vagrant halt
vagrant ssh

install plone

vagrant up
vagrant ssh
sudo apt-get update
sudo apt-get install python-setuptools python-dev build-essential libssl-dev libxml2-dev libxslt1-dev libbz2-dev libjpeg62-dev
sudo apt-get install libreadline-dev wv poppler-utils
sudo apt-get install git
wget --no-check-certificate https://launchpad.net/plone/3.3/3.3.6/+download/Plone-3.3.6-UnifiedInstaller.tgz

tar xf Plone-3.3.6-UnifiedInstaller.tgz
cd Plone-3.3.6-UnifiedInstaller.tgz
./install.sh standalone
  • 動作確認
cd ~/Plone/zinstance
# foreground/start/stop
bin/plonectl fg
bin/plonectl start
bin/plonectl stop
/sbin/ifconfig

追加の設定

  • sitecustomize.pyを入れる
vi /home/vagrant/Plone/Zope-2.10.13-final-py2.4/lib/python/sitecustomize.py
+ import sys
+ sys.setdefaultencoding("utf-8")
  • ploneのポートを適当に設定
vi /home/vagrant/Plone/zinstance/parts/instance/etc/zope.conf
+ <http-server>
+   address 12200
+ </http-server>
+ <ftp-server>
+   address 12221
+ </ftp-server>

2011-12-11

[] Emacs Lispテクニックバイブル 感想 00:29  Emacs Lispテクニックバイブル 感想を含むブックマーク  Emacs Lispテクニックバイブル 感想のブックマークコメント

Emacs Lisp テクニックバイブルを入手して読了。

読み終わるのに結構時間かかった。

http://www.amazon.co.jp/dp/4774148970


  • 一般的な言語の教科書っぽい感じ
  • 練習問題って項目だけど、かならず問題って訳ではなくて、操作の例とかの場合も
  • まとめがいい感じ

Emacs Lispをバリバリ書かない人には、間違いなく良い本。

書いている人にとっても、本の後半、テストデバッグ、モード作成、外部プログラムとの協調、非同期処理あたりは面白い感じ。

前作のEmacsテクニックバイブルと違って、即使える系の本じゃないけど、エディタマニアー↑な自分には面白かった。


Emacs本、あんまり頻繁に出る訳じゃないから、

たまに出る本ががっかりだと、残念感が半端無いから、良い本で本当によかった。

rubikitchrubikitch 2012/01/14 23:57 書評ありがとうございます!!
役立ったようで嬉しいです。

この本はオーソドックスな教科書スタイルと逆引き本を混ぜてみました。