sbire 0.0.8 → 0.0.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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