しゃべるペンギン

インターネットの広大な領域には、スマートホーム、拡張現実眼鏡、新しい「モノのインターネット」、および想像可能な未来のその他の視点に関する記事がたくさんあります。 それが明るくなるか、ノワールサイバーパンクの「良い」伝統であるかどうかは時が経てばわかりますが、今のところ私たちはそれに向かって小さな一歩を踏み出します。



出版物のタイトルで推測したように、音声合成に焦点を当てます。 私が出会ったものをどのように実装したかを説明します。 私はオリジナルではない、私は祭りを使用しました。



開始する



件名:





-インストール、問題は発生しないはずです。

- スクリプトの例



バッテリーアラート



スクリプトはステータスと請求を認識します。 充電に接続されておらず、充電が50%未満の場合、充電を報告します。



#!/bin/bash scripts="$HOME/.bin/festival/" charge=$(cat /sys/class/power_supply/BAT0/capacity) procent=$(${scripts}pluralform.sh $charge   ) status=$(cat /sys/class/power_supply/BAT0/status) text=$(echo "  $charge $procent") critical="  ." if [ "$status" == 'Discharging' ] && [ $charge -gt 10 -a $charge -lt 50 ]; then ${scripts}say.sh "$text" elif [ "$status" == 'Discharging' ] && [ $charge -lt 10 ]; then ${scripts}say.sh "$critical" fi exit
      
      





偏角



 #!/usr/bin/env bash n=$(($1 % 100)) n1=$(($n % 10)) if [ $n -gt 10 -a $n -lt 20 ]; then echo $4; elif [ $n1 -gt 1 -a $n1 -lt 5 ]; then echo $3; elif [ $n1 -eq 1 ]; then echo $2; else echo $4 fi
      
      





スクリプトは、DATのファイルを考慮に入れてwavを生成します。 現在の音量を記憶し、最適な値を設定します。 ボリュームを再生して戻します。 現在のwavファイルを削除します。



 #!/bin/bash data="$HOME/.bin/festival/data" ru="(voice_msu_ru_nsh_clunits)" volume=$(amixer | grep -o [0-9]* | sed "5 ! d") i=$(ls -r $data | grep -o [0-9]* | sed "1 ! d") if test -z "$i"; then i=1; elif test -f "$data/saytext_$i.wav"; then i=$(($i+1)); fi echo "$1" | text2wave -o $data/saytext_$i.wav -eval $ru > /dev/null 2>&1 amixer set Master 67% > /dev/null 2>&1 aplay $data/saytext_$i.wav > /dev/null 2>&1 aplay=$(ps -el | grep aplay | wc -l) if [ $aplay -eq 0 ]; then amixer set Master $volume% > /dev/null 2>&1; fi rm -f $data/saytext_$i.wav
      
      





Gmailを確認しています



ほぼ完全なgem gmailソリューションが見つかりました。



このソリューションの利点:

-ラベルごとのメッセージ数に関するアラート。 最初に、サイトにラベル付きのフィルターを作成する必要があります。

-メッセージのヘッダーとテキストを読み取る機能(実装されていません)。



 # coding: utf-8 require 'gmail' require 'yaml' Gmail.new("login", "password") do |gmail| @festival = "$HOME/.bin/festival/" @labels = {"INBOX" => "", "Search job" => " ", "Music" => "", "Advertising" => "", "Education" => "", "Interesting" => ""} def check_letters(gmail) counts = {} @labels.each do |k,v| h = {k => gmail.mailbox(k).count(:unread)} counts.merge!(h) end return counts end def read_counts_letters unless File.exist?(".gmail.yml") return {} end old_counts = YAML::load(File.open(".gmail.yml")) return old_counts end def save_counts_letters(counts) system("touch .gmail.yml") if File.exist?(".gmail.yml") File.open(".gmail.yml", "w") do |f| f.write counts.to_yaml end end def check_new_counts_letters(counts, old_counts) counts.each do |k, v| if old_counts.empty? || v < old_counts[k] count = v else count = v - old_counts[k] end say_new_counts(k, count) end end def say_new_counts(k, count) unless count == 0 text = pluralform(count) count = "+" if count == 1 all = "  #{count} #{text}" part = "#{count} #{text}   #{@labels[k]}" if k == "INBOX" system("#{@festival}say.sh '#{all}'") else system("#{@festival}say.sh '#{part}'") end end end def pluralform(count) n = count % 100 m = n % 10 msg = ['', '', ''] if n > 10 && n < 20 return msg[2] elsif m > 1 && m < 5 return msg[1] elsif m == 1 return msg[0] else return msg[2] end end counts = check_letters(gmail) old_counts = read_counts_letters check_new_counts_letters(counts, old_counts) save_counts_letters(counts) gmail.logout end
      
      





問題点





再考



しばらくして、多くのオプションを試した後、pulseaudioを使用してフローを制御しました。



 pcm.pulse { type pulse } ctl.pulse { type pulse } pcm.!default { type pulse } ctl.!default { type pulse }
      
      





gem festを書くことで、ルビーのbashスクリプトを書き直しました。



 # coding: utf-8 # class Fest def say(string, params = {}) init(params) check_conditions make_wav(string) expect_if_paplay_now check_optimal_volume play_wav end def init(params) #    @params = params @path = @params[:path] || '/tmp' @current_volume = `amixer | grep -o '[0-9]*' | sed "5 ! d"`.to_i @index = `ls -r #{@path} | grep -o '[0-9]*' | sed "1 ! d"`.to_i @min_volume = @params[:down_volume[0]] || 20 @max_volume = @params[:down_volume[1]] || 60 @step = @params[:down_volume[2]] || 4 end def check_optimal_volume #    @volume = @current_volume - @current_volume / 10 * @step optimize_min_and_max_volume end def optimize_min_and_max_volume @optimize_volume = ( if @current_volume > @max_volume @max_volume elsif @current_volume < @min_volume @min_volume else @current_volume end ) end def check_conditions #   check_light check_home_theater check_say_wav end def check_light # ,    exit if @params[:backlight].nil? && `xbacklight`.to_i == 0 end def check_home_theater #      xbmc = `ps -el | grep xbmc | wc -l`.to_i vlc = `ps -el | grep vlc | wc -l`.to_i kodi = `ps -el | grep kodi | wc -l`.to_i exit if xbmc > 0 || vlc > 0 || kodi > 0 end def check_say_wav # index wav file @index > 0 ? @index += 1 : @index = 1 end def make_wav(string) #  wav (c mp3  ) system("echo '#{string}' | text2wave -o #{@path}/say_#{@index}.wav \ -eval '(#{@params[:language] || 'voice_msu_ru_nsh_clunits'})' \ > /dev/null 2>&1") end def change_volume(volume) #   system("amixer set Master #{volume}% > /dev/null 2>&1") end def expect_if_paplay_now #    loop do break if `ps -el | grep paplay | wc -l`.to_i == 0 sleep 1 end end #    #    def turn_down_volume @inputs = `pactl list sink-inputs | grep № | grep -o '[0-9]*'`.split("\n") @inputs.each do |input| volume = @current_volume loop do system("pactl set-sink-input-volume #{input} '#{volume * 655}'") volume -= @step break if volume < @volume end end end def play_wav #  wav turn_down_volume system("paplay #{@path}/say_#{@index}.wav \ --volume='#{@optimize_volume * 655}' > /dev/null 2>&1") return_current_volume delete_wav end #    def return_current_volume @inputs.each do |input| volume = @volume loop do system("pactl set-sink-input-volume #{input} '#{volume * 655}'") volume += @step break if volume > @current_volume end end end def delete_wav #  wav system("rm -f #{@path}/say_#{@index}.wav") end def pluralform(number, array) #  n = number % 100 m = n % 10 if n > 10 && n < 20 array[2] elsif m > 1 && m < 5 array[1] elsif m == 1 array[0] else array[2] end end end
      
      





クロンタブ



 PATH=$(echo $PATH) SHELL=/bin/bash GEM_HOME=$(gem environment gemdir) GEM_PATH=$(gem environment gemdir) DISPLAY=:0 */10 * * * * ~/.bin/festival/charge */20 * * * * ~/.bin/festival/gmail */30 * * * * ~/.bin/festival/quotes
      
      





結果



-crontabでの安定した作業

-音楽はバックグラウンドで再生されます

-スムーズな音量ダウンとリターン

-メッセージは現在の音量で再生されます(最小および最大以内の場合)



不快な瞬間:

-映画を見た後、音量をリセットする必要があります

-時々、声の演技がエコーされる(まれに)

-女性の声はありません



PS



gem "fest"を除くすべてのスクリプト、古いバージョン。 書き直されたスクリプトデモ



ご清聴ありがとうございました。



All Articles