sbire 0.0.8 → 0.0.10

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 23a66e9330db17e711a672a9f27b315383b4adbb
4
+ data.tar.gz: ccfd9923fbf7e9eef0f4c6dbba29a7c58d6076ca
5
+ SHA512:
6
+ metadata.gz: 6a41d6e3dc882502f8bddc81076342196557bca4a603ee9120cd4a8e0e171c168c402b8351a10da4ec2a447581566e9bfb2d7530ddefdee93e677fea8391cad2
7
+ data.tar.gz: 55a55882ec81f07801d7353c5ef21a5c7bc92646535d123e9d51fec82e00ce1561b4cabe89101b08617423814430a88e9540ab5f48f98b132818ca589215be41
data/bin/sbire CHANGED
@@ -1,4 +1,4 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
3
  require_relative '../lib/sbire'
4
- Sbire.run(ARGV)
4
+ Sbire::Command.new(ARGV).call
@@ -1,92 +1,10 @@
1
- require_relative 'notifier'
2
- require_relative 'audio_converter'
3
- require_relative 'command_manager'
4
- require_relative 'audio_recorder'
5
- require_relative 'save_manager'
6
- require_relative 'sbire_config'
7
- require_relative 'pid_manager'
8
- require_relative 'os'
1
+ require_relative 'sbire/command'
2
+ require_relative 'sbire/notifier'
3
+ require_relative 'sbire/audio_converter'
4
+ require_relative 'sbire/command_manager'
5
+ require_relative 'sbire/audio_recorder'
6
+ require_relative 'sbire/save_manager'
7
+ require_relative 'sbire/sbire_config'
8
+ require_relative 'sbire/pid_manager'
9
+ require_relative 'sbire/os'
9
10
  require 'rest_client'
10
-
11
- class Sbire
12
-
13
- attr_accessor :command
14
-
15
- def self.run(argv)
16
- self.new(argv).call
17
- end
18
-
19
- def initialize(argv)
20
- @command = argv.first
21
- end
22
-
23
- def call
24
- if ["start", "stop", "save", "install"].include?(command)
25
- send(command)
26
- else
27
- show("Command not found")
28
- end
29
- end
30
-
31
- private
32
- def start
33
- stop
34
- show("Sbire is listening your voice")
35
- audio_recorder.start
36
- audio_converter.start do |results, index|
37
- command_manager.execute(results, index)
38
- end
39
- end
40
-
41
- def stop
42
- audio_recorder.stop
43
- audio_converter.stop
44
- end
45
-
46
- def save
47
- stop
48
- show("Sbire is listening your voice")
49
- audio_recorder.start
50
- recreate_text_file
51
- audio_converter.start do |results, index|
52
- save_manager.save(results, index) if results
53
- end
54
- end
55
-
56
- def install
57
- home = Dir.home
58
- config_file = "config_#{OS.familly}.yml"
59
- FileUtils.mkdir_p("#{home}/.sbire/out")
60
- dirname = File.dirname(__FILE__)
61
- path = "#{dirname}/../files/#{config_file}"
62
- FileUtils.copy(path, "#{home}/.sbire/config.yml")
63
- end
64
-
65
- def recreate_text_file
66
- File.write(SbireConfig.text_file, '')
67
- end
68
-
69
- def command_manager
70
- @command_manager ||= CommandManager.new(SbireConfig.command_path)
71
- end
72
-
73
- def audio_recorder
74
- @audio_recorder ||= AudioRecorder.new(SbireConfig.out_file, pid_manager)
75
- end
76
-
77
- def audio_converter
78
- @audio_converter ||= AudioConverter.new(pid_manager)
79
- end
80
-
81
- def save_manager
82
- @save_manager ||= SaveManager.new
83
- end
84
-
85
- def show(message)
86
- Notifier.call(message)
87
- end
88
-
89
- def pid_manager
90
- @pid_manager ||= PidManager.new
91
- end
92
- end
@@ -0,0 +1,72 @@
1
+ require 'json'
2
+ require 'fileutils'
3
+ require 'rest_client'
4
+
5
+ module Sbire
6
+ class AudioConverter
7
+ attr_accessor :pid_manager
8
+ def initialize(pid_manager)
9
+ @pid_manager = pid_manager
10
+ end
11
+
12
+ def start(&block)
13
+ FileUtils.rm_rf("#{SbireConfig.out_path}/.")
14
+ pid = listen_audio(block)
15
+ pid_manager.store(self, pid)
16
+ end
17
+
18
+ def stop
19
+ pid_manager.kill(self)
20
+ end
21
+
22
+ private
23
+
24
+ def listen_audio(block)
25
+ fork do
26
+ index = 1
27
+ stop = false
28
+ hypotheses = []
29
+
30
+ while stop == false
31
+ Thread.new(index) do |i|
32
+ if File.exist?(filename(i + 1))
33
+ index += 1
34
+ hypotheses[i - 1] = send_to_google(filename(i))
35
+ block.call(hypotheses, i - 1)
36
+ stop = true if ENV["mode"] == "test"
37
+ end
38
+ end
39
+ sleep 0.1
40
+ end
41
+ end
42
+ end
43
+
44
+ def send_to_google(path)
45
+ file = File.read(path)
46
+ begin
47
+ response = RestClient.post url,
48
+ file,
49
+ content_type: 'audio/x-flac; rate=16000'
50
+ read_response(response.to_str) if response.code == 200
51
+ rescue => e
52
+ puts e
53
+ return [""]
54
+ end
55
+ end
56
+
57
+ def filename(index)
58
+ index = "%03d" % index
59
+ "#{SbireConfig.out_file}#{index}.flac"
60
+ end
61
+
62
+ def read_response(text)
63
+ data = JSON.parse(text)
64
+ data['hypotheses'].map {|ut| [ut['utterance'], ut['confidence']] }.first
65
+ end
66
+
67
+ def url
68
+ lang = SbireConfig.lang
69
+ "https://www.google.com/speech-api/v1/recognize?lang=#{lang}"
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,23 @@
1
+ module Sbire
2
+ class AudioRecorder
3
+ attr_accessor :path, :pid_manager
4
+ def initialize(path, pid_manager)
5
+ @path = path
6
+ @pid_manager = pid_manager
7
+ end
8
+
9
+ def start
10
+ pid = record_audio
11
+ pid_manager.store(self, pid)
12
+ end
13
+
14
+ def stop
15
+ pid_manager.kill(self)
16
+ end
17
+
18
+ private
19
+ def record_audio
20
+ fork { exec "sox -t alsa -r 22050 default #{path}.flac -q silence -l 1 0 1% 1 1.0 1% rate 16k : newfile : restart" }
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,84 @@
1
+ module Sbire
2
+ class Command
3
+
4
+ attr_accessor :command
5
+
6
+ def self.run(argv)
7
+ self.new(argv).call
8
+ end
9
+
10
+ def initialize(argv)
11
+ @command = argv.first
12
+ end
13
+
14
+ def call
15
+ if ["start", "stop", "save", "install"].include?(command)
16
+ send(command)
17
+ else
18
+ show("Command not found")
19
+ end
20
+ end
21
+
22
+ private
23
+ def start
24
+ stop
25
+ show("Sbire is listening your voice")
26
+ audio_recorder.start
27
+ audio_converter.start do |results, index|
28
+ command_manager.execute(results, index)
29
+ end
30
+ end
31
+
32
+ def stop
33
+ audio_recorder.stop
34
+ audio_converter.stop
35
+ end
36
+
37
+ def save
38
+ stop
39
+ show("Sbire is listening your voice")
40
+ audio_recorder.start
41
+ recreate_text_file
42
+ audio_converter.start do |results, index|
43
+ save_manager.save(results, index) if results
44
+ end
45
+ end
46
+
47
+ def install
48
+ home = Dir.home
49
+ config_file = "config_#{OS.familly}.yml"
50
+ FileUtils.mkdir_p("#{home}/.sbire/out")
51
+ dirname = File.dirname(__FILE__)
52
+ path = "#{dirname}/../../files/#{config_file}"
53
+ FileUtils.copy(path, "#{home}/.sbire/config.yml")
54
+ end
55
+
56
+ def recreate_text_file
57
+ File.write(SbireConfig.text_file, '')
58
+ end
59
+
60
+ def command_manager
61
+ @command_manager ||= CommandManager.new(SbireConfig.command_path)
62
+ end
63
+
64
+ def audio_recorder
65
+ @audio_recorder ||= AudioRecorder.new(SbireConfig.out_file, pid_manager)
66
+ end
67
+
68
+ def audio_converter
69
+ @audio_converter ||= AudioConverter.new(pid_manager)
70
+ end
71
+
72
+ def save_manager
73
+ @save_manager ||= SaveManager.new
74
+ end
75
+
76
+ def show(message)
77
+ Notifier.call(message)
78
+ end
79
+
80
+ def pid_manager
81
+ @pid_manager ||= PidManager.new
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,29 @@
1
+ require 'yaml'
2
+
3
+ module Sbire
4
+ class CommandManager
5
+ attr_accessor :commands
6
+
7
+ def initialize(path)
8
+ @commands = YAML.load_file(path) if File.exist?(path)
9
+ end
10
+
11
+ def execute(hypotheses, index)
12
+ current_hypothese = hypotheses[index]
13
+ unless current_hypothese.first.empty?
14
+ command = find(current_hypothese)
15
+ system("#{command} &")
16
+ return command
17
+ end
18
+ end
19
+
20
+ private
21
+ def find(hypotheses)
22
+ hypothese = hypotheses.first.downcase
23
+ if commands
24
+ commands.each_pair {|key, value| return key if value.include?(hypothese)}
25
+ end
26
+ return hypothese
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,10 @@
1
+ require_relative 'sbire_config'
2
+
3
+ module Sbire
4
+ class Notifier
5
+ def self.call(message)
6
+ command = SbireConfig.notify_command % { message: message }
7
+ system(command)
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,25 @@
1
+ module Sbire
2
+ class OS
3
+ def self.familly
4
+ return "win" if OS.windows?
5
+ return "linux" if OS.unix? || OS.linux?
6
+ return "mac" if OS.mac?
7
+ end
8
+
9
+ def self.windows?
10
+ (/cygwin|mswin|mingw|bccwin|wince|emx/ =~ RUBY_PLATFORM) != nil
11
+ end
12
+
13
+ def self.mac?
14
+ (/darwin/ =~ RUBY_PLATFORM) != nil
15
+ end
16
+
17
+ def self.unix?
18
+ !OS.windows?
19
+ end
20
+
21
+ def self.linux?
22
+ OS.unix? and not OS.mac?
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,20 @@
1
+ module Sbire
2
+ class PidManager
3
+ def store(object, pid)
4
+ File.open("/tmp/#{class_name(object)}.pid", 'w') {|file| file.write(pid)}
5
+ end
6
+
7
+ def kill(object)
8
+ if File.exists?("/tmp/#{class_name(object)}.pid")
9
+ pid = File.read("/tmp/#{class_name(object)}.pid")
10
+ system("kill #{pid}")
11
+ end
12
+ end
13
+
14
+ private
15
+
16
+ def class_name(object)
17
+ object.class.name.split('::').last
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,36 @@
1
+ module Sbire
2
+ class SaveManager
3
+ attr_accessor :last_index, :max_index
4
+
5
+ def initialize
6
+ @last_index = 0
7
+ @max_index = 0
8
+ end
9
+
10
+ def save(hypotheses, index)
11
+ compute_max_index(index)
12
+ hypotheses = current_hypotheses(hypotheses)
13
+ unless hypotheses.include?(nil)
14
+ append_to_file(hypotheses)
15
+ @last_index = index + 1
16
+ end
17
+ end
18
+
19
+ private
20
+
21
+ def compute_max_index(index)
22
+ @max_index = index if @max_index < index
23
+ end
24
+
25
+ def current_hypotheses(hypotheses)
26
+ hypotheses.map { |hypothese| hypothese.first }[last_index..max_index]
27
+ end
28
+
29
+ def append_to_file(hypotheses)
30
+ text = hypotheses.join(" ") + " "
31
+ if text != " "
32
+ File.open(SbireConfig.text_file, 'ab+') {|file| file.write(text)}
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,44 @@
1
+ require 'yaml'
2
+
3
+ module Sbire
4
+ class SbireConfig
5
+ def self.config_path
6
+ "#{base_directory}/config.yml"
7
+ end
8
+
9
+ def self.base_directory
10
+ "#{Dir.home}/.sbire"
11
+ end
12
+
13
+ def self.lang
14
+ config["lang"] ||= "en-US"
15
+ end
16
+
17
+ def self.out_path
18
+ config["out_path"] ||= "#{base_directory}/out/"
19
+ end
20
+
21
+ def self.out_file
22
+ config["out_file"] ||= "#{out_path}.audiofile"
23
+ end
24
+
25
+ def self.text_file
26
+ config["text_file"] ||= "#{base_directory}/text"
27
+ end
28
+
29
+ def self.command_path
30
+ config["command_path"] ||= "#{base_directory}/commands.yml"
31
+ end
32
+
33
+ def self.notify_command
34
+ config["notify_command"]
35
+ end
36
+
37
+ private
38
+
39
+ def self.config
40
+ return @config if @config
41
+ @config = YAML.load_file(config_path) || {}
42
+ end
43
+ end
44
+ end
metadata CHANGED
@@ -1,8 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sbire
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.8
5
- prerelease:
4
+ version: 0.0.10
6
5
  platform: ruby
7
6
  authors:
8
7
  - Guirec Corbel
@@ -14,17 +13,15 @@ dependencies:
14
13
  - !ruby/object:Gem::Dependency
15
14
  name: rest-client
16
15
  requirement: !ruby/object:Gem::Requirement
17
- none: false
18
16
  requirements:
19
- - - ! '>='
17
+ - - '>='
20
18
  - !ruby/object:Gem::Version
21
19
  version: '0'
22
20
  type: :runtime
23
21
  prerelease: false
24
22
  version_requirements: !ruby/object:Gem::Requirement
25
- none: false
26
23
  requirements:
27
- - - ! '>='
24
+ - - '>='
28
25
  - !ruby/object:Gem::Version
29
26
  version: '0'
30
27
  description: Sbire is a command line tool that recognize your voice and execute commands
@@ -36,15 +33,16 @@ extensions: []
36
33
  extra_rdoc_files: []
37
34
  files:
38
35
  - bin/sbire
39
- - lib/audio_converter.rb
40
- - lib/audio_recorder.rb
41
- - lib/os.rb
42
36
  - lib/sbire.rb
43
- - lib/command_manager.rb
44
- - lib/save_manager.rb
45
- - lib/sbire_config.rb
46
- - lib/notifier.rb
47
- - lib/pid_manager.rb
37
+ - lib/sbire/audio_converter.rb
38
+ - lib/sbire/audio_recorder.rb
39
+ - lib/sbire/os.rb
40
+ - lib/sbire/command_manager.rb
41
+ - lib/sbire/save_manager.rb
42
+ - lib/sbire/sbire_config.rb
43
+ - lib/sbire/notifier.rb
44
+ - lib/sbire/pid_manager.rb
45
+ - lib/sbire/command.rb
48
46
  - files/config_win.yml
49
47
  - files/config_mac.yml
50
48
  - files/config_linux.yml
@@ -52,26 +50,25 @@ files:
52
50
  homepage: https://github.com/GCorbel/sbire
53
51
  licenses:
54
52
  - MIT
53
+ metadata: {}
55
54
  post_install_message:
56
55
  rdoc_options: []
57
56
  require_paths:
58
57
  - lib
59
58
  required_ruby_version: !ruby/object:Gem::Requirement
60
- none: false
61
59
  requirements:
62
- - - ! '>='
60
+ - - '>='
63
61
  - !ruby/object:Gem::Version
64
62
  version: '0'
65
63
  required_rubygems_version: !ruby/object:Gem::Requirement
66
- none: false
67
64
  requirements:
68
- - - ! '>='
65
+ - - '>='
69
66
  - !ruby/object:Gem::Version
70
67
  version: '0'
71
68
  requirements: []
72
69
  rubyforge_project:
73
- rubygems_version: 1.8.23
70
+ rubygems_version: 2.0.3
74
71
  signing_key:
75
- specification_version: 3
72
+ specification_version: 4
76
73
  summary: The henchman who do what you say
77
74
  test_files: []
@@ -1,70 +0,0 @@
1
- require 'json'
2
- require 'fileutils'
3
- require 'rest_client'
4
-
5
- class AudioConverter
6
- attr_accessor :pid_manager
7
- def initialize(pid_manager)
8
- @pid_manager = pid_manager
9
- end
10
-
11
- def start(&block)
12
- FileUtils.rm_rf("#{SbireConfig.out_path}/.")
13
- pid = listen_audio(block)
14
- pid_manager.store(self, pid)
15
- end
16
-
17
- def stop
18
- pid_manager.kill(self)
19
- end
20
-
21
- private
22
-
23
- def listen_audio(block)
24
- fork do
25
- index = 1
26
- stop = false
27
- hypotheses = []
28
-
29
- while stop == false
30
- Thread.new(index) do |i|
31
- if File.exist?(filename(i + 1))
32
- index += 1
33
- hypotheses[i - 1] = send_to_google(filename(i))
34
- block.call(hypotheses, i - 1)
35
- stop = true if ENV["mode"] == "test"
36
- end
37
- end
38
- sleep 0.1
39
- end
40
- end
41
- end
42
-
43
- def send_to_google(path)
44
- file = File.read(path)
45
- begin
46
- response = RestClient.post url,
47
- file,
48
- content_type: 'audio/x-flac; rate=16000'
49
- read_response(response.to_str) if response.code == 200
50
- rescue => e
51
- puts e
52
- return [""]
53
- end
54
- end
55
-
56
- def filename(index)
57
- index = "%03d" % index
58
- "#{SbireConfig.out_file}#{index}.flac"
59
- end
60
-
61
- def read_response(text)
62
- data = JSON.parse(text)
63
- data['hypotheses'].map {|ut| [ut['utterance'], ut['confidence']] }.first
64
- end
65
-
66
- def url
67
- lang = SbireConfig.lang
68
- "https://www.google.com/speech-api/v1/recognize?lang=#{lang}"
69
- end
70
- end
@@ -1,21 +0,0 @@
1
- class AudioRecorder
2
- attr_accessor :path, :pid_manager
3
- def initialize(path, pid_manager)
4
- @path = path
5
- @pid_manager = pid_manager
6
- end
7
-
8
- def start
9
- pid = record_audio
10
- pid_manager.store(self, pid)
11
- end
12
-
13
- def stop
14
- pid_manager.kill(self)
15
- end
16
-
17
- private
18
- def record_audio
19
- fork { exec "sox -t alsa -r 22050 default #{path}.flac -q silence -l 1 0 1% 1 1.0 1% rate 16k : newfile : restart" }
20
- end
21
- end
@@ -1,27 +0,0 @@
1
- require 'yaml'
2
-
3
- class CommandManager
4
- attr_accessor :commands
5
-
6
- def initialize(path)
7
- @commands = YAML.load_file(path) if File.exist?(path)
8
- end
9
-
10
- def execute(hypotheses, index)
11
- current_hypothese = hypotheses[index]
12
- unless current_hypothese.first.empty?
13
- command = find(current_hypothese)
14
- system("#{command} &")
15
- return command
16
- end
17
- end
18
-
19
- private
20
- def find(hypotheses)
21
- hypothese = hypotheses.first.downcase
22
- if commands
23
- commands.each_pair {|key, value| return key if value.include?(hypothese)}
24
- end
25
- return hypothese
26
- end
27
- end
@@ -1,8 +0,0 @@
1
- require_relative 'sbire_config'
2
-
3
- class Notifier
4
- def self.call(message)
5
- command = SbireConfig.notify_command % { message: message }
6
- system(command)
7
- end
8
- end
data/lib/os.rb DELETED
@@ -1,23 +0,0 @@
1
- class OS
2
- def self.familly
3
- return "win" if OS.windows?
4
- return "linux" if OS.unix? || OS.linux?
5
- return "mac" if OS.mac?
6
- end
7
-
8
- def self.windows?
9
- (/cygwin|mswin|mingw|bccwin|wince|emx/ =~ RUBY_PLATFORM) != nil
10
- end
11
-
12
- def self.mac?
13
- (/darwin/ =~ RUBY_PLATFORM) != nil
14
- end
15
-
16
- def self.unix?
17
- !OS.windows?
18
- end
19
-
20
- def self.linux?
21
- OS.unix? and not OS.mac?
22
- end
23
- end
@@ -1,12 +0,0 @@
1
- class PidManager
2
- def store(object, pid)
3
- class_name = object.class.name
4
- File.open("/tmp/#{class_name}.pid", 'w') {|file| file.write(pid)}
5
- end
6
-
7
- def kill(object)
8
- class_name = object.class.name
9
- pid = File.read("/tmp/#{class_name}.pid")
10
- system("kill #{pid}")
11
- end
12
- end
@@ -1,34 +0,0 @@
1
- class SaveManager
2
- attr_accessor :last_index, :max_index
3
-
4
- def initialize
5
- @last_index = 0
6
- @max_index = 0
7
- end
8
-
9
- def save(hypotheses, index)
10
- compute_max_index(index)
11
- hypotheses = current_hypotheses(hypotheses)
12
- unless hypotheses.include?(nil)
13
- append_to_file(hypotheses)
14
- @last_index = index + 1
15
- end
16
- end
17
-
18
- private
19
-
20
- def compute_max_index(index)
21
- @max_index = index if @max_index < index
22
- end
23
-
24
- def current_hypotheses(hypotheses)
25
- hypotheses.map { |hypothese| hypothese.first }[last_index..max_index]
26
- end
27
-
28
- def append_to_file(hypotheses)
29
- text = hypotheses.join(" ") + " "
30
- if text != " "
31
- File.open(SbireConfig.text_file, 'ab+') {|file| file.write(text)}
32
- end
33
- end
34
- end
@@ -1,42 +0,0 @@
1
- require 'yaml'
2
-
3
- class SbireConfig
4
- def self.config_path
5
- "#{base_directory}/config.yml"
6
- end
7
-
8
- def self.base_directory
9
- "#{Dir.home}/.sbire"
10
- end
11
-
12
- def self.lang
13
- config["lang"] ||= "en-US"
14
- end
15
-
16
- def self.out_path
17
- config["out_path"] ||= "#{base_directory}/out/"
18
- end
19
-
20
- def self.out_file
21
- config["out_file"] ||= "#{out_path}.audiofile"
22
- end
23
-
24
- def self.text_file
25
- config["text_file"] ||= "#{base_directory}/text"
26
- end
27
-
28
- def self.command_path
29
- config["command_path"] ||= "#{base_directory}/commands.yml"
30
- end
31
-
32
- def self.notify_command
33
- config["notify_command"]
34
- end
35
-
36
- private
37
-
38
- def self.config
39
- return @config if @config
40
- @config = YAML.load_file(config_path) || {}
41
- end
42
- end