yandex_speech_api 1.1.2
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.
- checksums.yaml +7 -0
- data/Gemfile +16 -0
- data/LICENSE +9 -0
- data/README.md +101 -0
- data/lib/yandex_speech.rb +253 -0
- data/lib/yandex_speech/connection.rb +52 -0
- data/lib/yandex_speech/emotion.rb +39 -0
- data/lib/yandex_speech/format.rb +38 -0
- data/lib/yandex_speech/helpers.rb +52 -0
- data/lib/yandex_speech/key.rb +106 -0
- data/lib/yandex_speech/language.rb +59 -0
- data/lib/yandex_speech/mp3_player.rb +33 -0
- data/lib/yandex_speech/mp3_player/base.rb +72 -0
- data/lib/yandex_speech/mp3_player/linux_mp3_player.rb +41 -0
- data/lib/yandex_speech/mp3_player/mac_mp3_player.rb +22 -0
- data/lib/yandex_speech/project_structure.rb +30 -0
- data/lib/yandex_speech/speaker.rb +103 -0
- data/lib/yandex_speech/speed.rb +60 -0
- data/lib/yandex_speech/voice.rb +45 -0
- data/spec/spec_helper.rb +16 -0
- data/spec/yandex_speech/connection_spec.rb +24 -0
- data/spec/yandex_speech/emotion_spec.rb +34 -0
- data/spec/yandex_speech/format_spec.rb +30 -0
- data/spec/yandex_speech/helpers_spec.rb +20 -0
- data/spec/yandex_speech/key_spec.rb +58 -0
- data/spec/yandex_speech/language_spec.rb +36 -0
- data/spec/yandex_speech/mp3_player/base_spec.rb +25 -0
- data/spec/yandex_speech/mp3_player/linux_mp3_player_spec.rb +39 -0
- data/spec/yandex_speech/mp3_player_spec.rb +23 -0
- data/spec/yandex_speech/speed_spec.rb +33 -0
- data/spec/yandex_speech/voice_spec.rb +28 -0
- data/spec/yandex_speech_spec.rb +112 -0
- metadata +90 -0
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
module YandexSpeechApi
|
|
4
|
+
class Format
|
|
5
|
+
|
|
6
|
+
##
|
|
7
|
+
# List of allowed formats
|
|
8
|
+
#
|
|
9
|
+
# @return [Array<String>]
|
|
10
|
+
|
|
11
|
+
def self.list
|
|
12
|
+
%i(mp3 wav opus)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
# @return [Symbol]
|
|
16
|
+
# possible values: :mp3, :wav or :opus
|
|
17
|
+
|
|
18
|
+
attr_reader :type
|
|
19
|
+
|
|
20
|
+
def initialize(format)
|
|
21
|
+
@type = format.downcase.to_sym
|
|
22
|
+
|
|
23
|
+
raise FormatNotAllowed, format unless format_known? @type
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
private
|
|
27
|
+
|
|
28
|
+
def format_known?(format)
|
|
29
|
+
Format.list.include? format
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
##
|
|
33
|
+
# Raised when unknown format has been selected.
|
|
34
|
+
|
|
35
|
+
class FormatNotAllowed < YandexSpeechError
|
|
36
|
+
def initialize(format); super "Format '#{format}' not allowed for usage. To see list of allowed formats use Format#list" end; end
|
|
37
|
+
end # class Format
|
|
38
|
+
end # module YandexSpeechApi
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
module YandexSpeechApi
|
|
4
|
+
module Helpers
|
|
5
|
+
|
|
6
|
+
##
|
|
7
|
+
# From what OS we launched?
|
|
8
|
+
#
|
|
9
|
+
# @example #1
|
|
10
|
+
# recognize_operation_system # ==> :linux
|
|
11
|
+
#
|
|
12
|
+
# @example #2
|
|
13
|
+
# recognize_operation_system # ==> :unknown
|
|
14
|
+
#
|
|
15
|
+
# @return [Symbol]
|
|
16
|
+
# OS name
|
|
17
|
+
|
|
18
|
+
def self.recognize_operation_system
|
|
19
|
+
case RbConfig::CONFIG['host_os']
|
|
20
|
+
when /mswin|msys|mingw|cygwin|bccwin|wince|emc/
|
|
21
|
+
:windows
|
|
22
|
+
when /darwin|mac os/
|
|
23
|
+
:mac_os
|
|
24
|
+
when /linux/
|
|
25
|
+
:linux
|
|
26
|
+
else
|
|
27
|
+
:unknown
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
##
|
|
32
|
+
# Searches pathname for executable +cmd+.
|
|
33
|
+
#
|
|
34
|
+
# @return [Pathname, NilClass]
|
|
35
|
+
# Returns +Pathname+ if +cmd+ is present and executable.
|
|
36
|
+
# If search unsuccessful it returns +nil+.
|
|
37
|
+
|
|
38
|
+
def self.find_executable(cmd)
|
|
39
|
+
possible_extensions = ENV['PATHEXT'] ? ENV['PATHEXT'].split(';') : ['']
|
|
40
|
+
|
|
41
|
+
ENV['PATH'].split(File::PATH_SEPARATOR).each do |path|
|
|
42
|
+
possible_extensions.each do |extension|
|
|
43
|
+
exe = Pathname.new(File.join(path, "#{cmd}#{extension}"))
|
|
44
|
+
|
|
45
|
+
return exe if exe.executable? && exe.file?
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
return nil # search unsuccessful
|
|
50
|
+
end
|
|
51
|
+
end # module Helpers
|
|
52
|
+
end # module YandexSpeechApi
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
module YandexSpeechApi
|
|
4
|
+
class Key
|
|
5
|
+
class << self
|
|
6
|
+
|
|
7
|
+
##
|
|
8
|
+
# Sets global key.
|
|
9
|
+
#
|
|
10
|
+
# @param [Key, Symbol] new_key
|
|
11
|
+
#
|
|
12
|
+
# @exception InvalidGlobalKey
|
|
13
|
+
# raised when +new_key+ param have unexpected class.
|
|
14
|
+
|
|
15
|
+
def global_key=(new_key)
|
|
16
|
+
key_tmp = new_key.is_a?(Key) ? new_key : Key.new(new_key)
|
|
17
|
+
raise InvalidGlobalKey, key_tmp unless key_tmp.present?
|
|
18
|
+
@global_key = key_tmp
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
##
|
|
22
|
+
# @return [TrueClass, FalseClass]
|
|
23
|
+
# True if global key set, otherwise returns false.
|
|
24
|
+
|
|
25
|
+
def global_key?
|
|
26
|
+
!!global_key
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
private
|
|
30
|
+
|
|
31
|
+
##
|
|
32
|
+
# @return [Key, nil]
|
|
33
|
+
|
|
34
|
+
def global_key
|
|
35
|
+
@global_key
|
|
36
|
+
end
|
|
37
|
+
end # class << self
|
|
38
|
+
|
|
39
|
+
def initialize(key)
|
|
40
|
+
@instance_key = key
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
##
|
|
44
|
+
# Returns an key.
|
|
45
|
+
#
|
|
46
|
+
# @exception KeyNotDefined
|
|
47
|
+
# raised if both +instance key+ and +global key_ are not present
|
|
48
|
+
#
|
|
49
|
+
# @return [Key]
|
|
50
|
+
|
|
51
|
+
def get
|
|
52
|
+
if present?
|
|
53
|
+
return instance_key
|
|
54
|
+
elsif default?
|
|
55
|
+
return default.get
|
|
56
|
+
else
|
|
57
|
+
raise KeyNotDefined
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
##
|
|
62
|
+
# Key present?
|
|
63
|
+
#
|
|
64
|
+
# @return [TrueClass, FalseClass]
|
|
65
|
+
# returns +false+ if key is +:unknown+, otherwise - +true+.
|
|
66
|
+
|
|
67
|
+
def present?
|
|
68
|
+
!(instance_key == :unknown)
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
private
|
|
72
|
+
|
|
73
|
+
# @return [Symbol, String]
|
|
74
|
+
# possible values: :unknown or some string
|
|
75
|
+
|
|
76
|
+
attr_reader :instance_key
|
|
77
|
+
|
|
78
|
+
##
|
|
79
|
+
# @return [TrueClass, FalseClass]
|
|
80
|
+
# @see Key#global_key?
|
|
81
|
+
|
|
82
|
+
def default?
|
|
83
|
+
Key.global_key?
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
##
|
|
87
|
+
# @return [Key, nil]
|
|
88
|
+
# see Key#global_key
|
|
89
|
+
|
|
90
|
+
def default
|
|
91
|
+
Key.instance_variable_get :@global_key
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
##
|
|
95
|
+
# Raised when user tries to call #say method without key.
|
|
96
|
+
|
|
97
|
+
class KeyNotDefined < YandexSpeechError
|
|
98
|
+
def initialize; super "WARNING! You initialized Speaker class without key! It means you can not use YandexSpeechApi service. You can get your key there: https://tech.yandex.ru/speechkit" end; end
|
|
99
|
+
|
|
100
|
+
##
|
|
101
|
+
# Raised when global key going to be set with default values.
|
|
102
|
+
|
|
103
|
+
class InvalidGlobalKey < YandexSpeechError
|
|
104
|
+
def initialize(key); super "Global key '#{key}' can not been nil or :unknown" end; end
|
|
105
|
+
end # class Key
|
|
106
|
+
end # module YandexSpeechApi
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
module YandexSpeechApi
|
|
4
|
+
class Language # no-doc
|
|
5
|
+
|
|
6
|
+
##
|
|
7
|
+
# List of allowed languages
|
|
8
|
+
#
|
|
9
|
+
# @return [Array<Classes>]
|
|
10
|
+
|
|
11
|
+
def self.allowed_languages
|
|
12
|
+
@cached_list ||= Array(codes.keys)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def self.codes # no-doc
|
|
16
|
+
{
|
|
17
|
+
english: 'en-US',
|
|
18
|
+
russian: 'ru‑RU',
|
|
19
|
+
turkey: 'tr-TR',
|
|
20
|
+
ukrain: 'uk-UK',
|
|
21
|
+
}
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# @return [Symbol]
|
|
25
|
+
|
|
26
|
+
attr_reader :language
|
|
27
|
+
|
|
28
|
+
# @return [String]
|
|
29
|
+
|
|
30
|
+
def code
|
|
31
|
+
@code ||= Language.codes[@language]
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
##
|
|
35
|
+
# Creates new object instance.
|
|
36
|
+
#
|
|
37
|
+
# @param [String] language
|
|
38
|
+
# Selected language.
|
|
39
|
+
#
|
|
40
|
+
# @exception UnknownLanguageError
|
|
41
|
+
# Raised when language is unknown
|
|
42
|
+
#
|
|
43
|
+
# @return [Language]
|
|
44
|
+
|
|
45
|
+
def initialize(language)
|
|
46
|
+
@language = language.downcase.to_sym
|
|
47
|
+
|
|
48
|
+
unless Language.allowed_languages.include? @language
|
|
49
|
+
raise UnknownLanguageError, @language
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
##
|
|
54
|
+
# Raised when unknown language has been selected.
|
|
55
|
+
|
|
56
|
+
class UnknownLanguageError < YandexSpeechError
|
|
57
|
+
def initialize(lang); super "Unknown language selected: '#{lang}'. See Language#allowed_languages for list of allowed languages" end; end
|
|
58
|
+
end # class Language
|
|
59
|
+
end # module YandexSpeechApi
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
module YandexSpeechApi
|
|
4
|
+
module MP3_Player
|
|
5
|
+
|
|
6
|
+
##
|
|
7
|
+
# Creates MP3 player instance. Depends from OS.
|
|
8
|
+
#
|
|
9
|
+
# @exception UnknownOsError
|
|
10
|
+
# raised when OS unknown.
|
|
11
|
+
#
|
|
12
|
+
# @return [Linux_MP3_Player, Mac_MP3_Player]
|
|
13
|
+
|
|
14
|
+
def self.init
|
|
15
|
+
@player ||=
|
|
16
|
+
case Helpers::recognize_operation_system
|
|
17
|
+
when :linux
|
|
18
|
+
Linux_MP3_Player.new
|
|
19
|
+
when :mac_os
|
|
20
|
+
Mac_MP3_Player.new
|
|
21
|
+
else
|
|
22
|
+
raise UnknownOs
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
##
|
|
27
|
+
# Raised when MP3_Player#init can not recognize what operation system is
|
|
28
|
+
# used.
|
|
29
|
+
|
|
30
|
+
class UnknownOs < YandexSpeechError
|
|
31
|
+
def initialize; super "#{self.class}#recognize_operation_system cannot recognize your operation system!"; end; end
|
|
32
|
+
end # module Player
|
|
33
|
+
end # module YandexSpeechApi
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
module YandexSpeechApi
|
|
4
|
+
module MP3_Player
|
|
5
|
+
class Base # no-doc
|
|
6
|
+
|
|
7
|
+
##
|
|
8
|
+
# Plays sound
|
|
9
|
+
|
|
10
|
+
def play(filename)
|
|
11
|
+
@filename = Pathname.new filename
|
|
12
|
+
validate_file_presence
|
|
13
|
+
validate_mp3_format
|
|
14
|
+
validate_requirements
|
|
15
|
+
play_mp3
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
private
|
|
19
|
+
|
|
20
|
+
attr_reader :filename # no-doc
|
|
21
|
+
|
|
22
|
+
##
|
|
23
|
+
# no-doc
|
|
24
|
+
|
|
25
|
+
def validate_file_presence
|
|
26
|
+
raise FileNotFound, filename unless @filename.file?
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
##
|
|
30
|
+
# Raises an exception if +filename+ without '.mp3' extension
|
|
31
|
+
|
|
32
|
+
def validate_mp3_format
|
|
33
|
+
unless File.extname(filename).casecmp('.mp3').zero?
|
|
34
|
+
raise UnknownExtension, filename
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
##
|
|
39
|
+
# Play mp3
|
|
40
|
+
#
|
|
41
|
+
# @exception NotImplementedError
|
|
42
|
+
# raised if #play_mp3 was called, but not overridden in any MP3_Player child
|
|
43
|
+
|
|
44
|
+
def play_mp3
|
|
45
|
+
raise NotImplementedError, "Abstract class called"
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
##
|
|
49
|
+
# Validates OS requirements. Abstract
|
|
50
|
+
#
|
|
51
|
+
# @exception NotImplementedError
|
|
52
|
+
# raised if #validate_requirements was called, but not overridden in any MP3_Player child
|
|
53
|
+
|
|
54
|
+
def validate_requirements
|
|
55
|
+
raise NotImplementedError, "Abstract class called"
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
##
|
|
59
|
+
# Raised when +filename+ has wrong (not mp3) extension. Used to give
|
|
60
|
+
# minimal protection against files with unknown format.
|
|
61
|
+
|
|
62
|
+
class UnknownExtension < YandexSpeechError
|
|
63
|
+
def initialize(filename); super "Mp3 player can work only with files with '.mp3' extension. Please change extension for #{filename} if you sure that format is correct!'" end; end
|
|
64
|
+
|
|
65
|
+
##
|
|
66
|
+
# Raised when file not found
|
|
67
|
+
|
|
68
|
+
class FileNotFound < YandexSpeechError
|
|
69
|
+
def initialize(file); super "File #{file} not found!" end; end
|
|
70
|
+
end # class Base
|
|
71
|
+
end # module MP3_Player
|
|
72
|
+
end # module YandexSpeechApi
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
module YandexSpeechApi
|
|
4
|
+
module MP3_Player
|
|
5
|
+
class Linux_MP3_Player < MP3_Player::Base # no-doc
|
|
6
|
+
private
|
|
7
|
+
|
|
8
|
+
# @return [String]
|
|
9
|
+
# Path to +mpg123+ application
|
|
10
|
+
|
|
11
|
+
attr_reader :path_to_executable
|
|
12
|
+
|
|
13
|
+
##
|
|
14
|
+
# Check requirements.
|
|
15
|
+
#
|
|
16
|
+
# @exception ApplicationNotInstalled
|
|
17
|
+
# Raised if +mpg123+ not found.
|
|
18
|
+
|
|
19
|
+
def validate_requirements
|
|
20
|
+
@path_to_executable = Helpers::find_executable 'mpg123'
|
|
21
|
+
|
|
22
|
+
if path_to_executable.nil?
|
|
23
|
+
raise ApplicationNotInstalled , 'mpq123'
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
##
|
|
28
|
+
# no-doc
|
|
29
|
+
|
|
30
|
+
def play_mp3
|
|
31
|
+
`#{path_to_executable} -q '#{filename}'`
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
##
|
|
35
|
+
# Raised when necessary linux program not found.
|
|
36
|
+
|
|
37
|
+
class ApplicationNotInstalled < YandexSpeechError
|
|
38
|
+
def initialize(name); super "Program '#{name}' not found!" end; end
|
|
39
|
+
end # class Linux_MP3_Player
|
|
40
|
+
end # module MP3_Player
|
|
41
|
+
end # module YandexSpeechApi
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
module YandexSpeechApi
|
|
4
|
+
module MP3_Player
|
|
5
|
+
class Mac_MP3_Player < MP3_Player::Base
|
|
6
|
+
|
|
7
|
+
##
|
|
8
|
+
# no-doc
|
|
9
|
+
|
|
10
|
+
def validate_requirements
|
|
11
|
+
nil
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
##
|
|
15
|
+
# no-doc
|
|
16
|
+
|
|
17
|
+
def play_mp3
|
|
18
|
+
`afplay '#{filename}'`
|
|
19
|
+
end
|
|
20
|
+
end # class Mac_MP3_Player
|
|
21
|
+
end # module MP3_Player
|
|
22
|
+
end # module YandexSpeechApi
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
module YandexSpeechApi
|
|
4
|
+
# dependencies from core lib
|
|
5
|
+
require 'rbconfig'
|
|
6
|
+
require 'uri'
|
|
7
|
+
require 'net/http'
|
|
8
|
+
|
|
9
|
+
##
|
|
10
|
+
# Core class for all exceptions that can be raised in YandexSpeechApi lib..
|
|
11
|
+
|
|
12
|
+
class YandexSpeechError < StandardError; end
|
|
13
|
+
|
|
14
|
+
# project structure
|
|
15
|
+
|
|
16
|
+
##
|
|
17
|
+
# loads *.rb files in requested order
|
|
18
|
+
|
|
19
|
+
def self.load(**params)
|
|
20
|
+
params[:files].each do |f|
|
|
21
|
+
require File.join(__dir__, params[:folder].to_s, f)
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
private_class_method :load
|
|
25
|
+
|
|
26
|
+
load folder: 'mp3_player',
|
|
27
|
+
files: %w(base mac_mp3_player linux_mp3_player)
|
|
28
|
+
|
|
29
|
+
load files: %w(helpers mp3_player key language format voice emotion speed connection speaker)
|
|
30
|
+
end # module YandexSpeechApi
|