bach 0.0.1
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.
- data/README.md +74 -0
- data/bin/bach +35 -0
- data/bin/bachd +91 -0
- data/lib/bach/version.rb +3 -0
- data/lib/constable.rb +1 -0
- metadata +76 -0
data/README.md
ADDED
@@ -0,0 +1,74 @@
|
|
1
|
+
# Bach
|
2
|
+
|
3
|
+
In the later years of his life, Johann Sebastion Bach became increasingly
|
4
|
+
blind. His final works were dictated from his deathbed.
|
5
|
+
|
6
|
+
This project, Bach, provides text-to-speech as a service.
|
7
|
+
|
8
|
+
|
9
|
+
Up and running fast
|
10
|
+
-------------------
|
11
|
+
|
12
|
+
I've provided a Vagrant setup that will get you up and running fast. Install
|
13
|
+
the necessary gems using Bundler:
|
14
|
+
|
15
|
+
$ cd /path/to/checkout/of/bach
|
16
|
+
$ bundle
|
17
|
+
|
18
|
+
Ask Vagrant to bring up the server components for you:
|
19
|
+
|
20
|
+
$ cd /path/to/checkout/of/bach
|
21
|
+
$ bundle exec vagrant up
|
22
|
+
|
23
|
+
Ask Bach to translate a file full of text to an audio file:
|
24
|
+
|
25
|
+
$ cd /path/to/checkout/of/bach
|
26
|
+
$ bundle exec ./bin/bach < textfile > speech.mp3
|
27
|
+
|
28
|
+
That's it, text-to-speech with very little fuss.
|
29
|
+
|
30
|
+
Of course, if you want to use it as a real service on your network you'll
|
31
|
+
probably want to set it up a little differently. See the following sections on
|
32
|
+
Installing and Usage for information on how to setup your own text-to-speech
|
33
|
+
service.
|
34
|
+
|
35
|
+
|
36
|
+
Installing
|
37
|
+
----------
|
38
|
+
|
39
|
+
The server needs eSpeak and Lame installed. Mostly I do this using `apt-get`:
|
40
|
+
|
41
|
+
$ apt-get install espeak lame
|
42
|
+
|
43
|
+
You'll need a broker that talks Stomp somewhere on your network. I use Apache
|
44
|
+
Apollo, and I'm not totally sure if the code uses anything that's specific to
|
45
|
+
that. I'd love it to be broker-agnostic though, so if you have patches that'll
|
46
|
+
bring this closer to reality please send them to me!
|
47
|
+
|
48
|
+
|
49
|
+
Usage
|
50
|
+
-----
|
51
|
+
|
52
|
+
Run the server, somewhere that has eSpeak and Lame installed:
|
53
|
+
|
54
|
+
$ bachd --broker=stomp://mq.yourdomain.com:61613
|
55
|
+
|
56
|
+
Use the services on the command line. You don't need to have eSpeak
|
57
|
+
installed on your client machines, just Bach.
|
58
|
+
|
59
|
+
A brief example of what interacting with Bach looks like, here
|
60
|
+
converting the text of the Gettysberb address to an mp3:
|
61
|
+
|
62
|
+
$ curl -O http://history.eserver.org/gettysburg-address.txt
|
63
|
+
$ bach --broker=stomp://mq.yourdomain.com:61613 \
|
64
|
+
< ./gettysburg-address.txt > .//gettysburg-address.mp3
|
65
|
+
|
66
|
+
I explicitly state the broker in the above commands but if you leave out that
|
67
|
+
option it'll default to stomp://localhost:61613 ie it expects a broker running
|
68
|
+
on your local machine if you don't tell it otherwise.
|
69
|
+
|
70
|
+
|
71
|
+
Authors
|
72
|
+
-------
|
73
|
+
|
74
|
+
Craig R Webster <http://barkingiguana.com/>
|
data/bin/bach
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
#! /usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'base64'
|
4
|
+
require 'stomp'
|
5
|
+
require 'json'
|
6
|
+
require "getoptlong"
|
7
|
+
|
8
|
+
options = {}
|
9
|
+
argv = GetoptLong.new(
|
10
|
+
[ "--broker", "-b", GetoptLong::OPTIONAL_ARGUMENT ]
|
11
|
+
)
|
12
|
+
argv.each do |option, value|
|
13
|
+
options['broker'] = value if option == '--broker'
|
14
|
+
end
|
15
|
+
options['broker'] ||= 'stomp://127.0.0.1:61613'
|
16
|
+
|
17
|
+
text = ARGF.read
|
18
|
+
encoded_text = Base64.encode64 text
|
19
|
+
command = { text: encoded_text }
|
20
|
+
command_json = JSON.generate command
|
21
|
+
|
22
|
+
results = '/queue/bach.results-' + Process.pid.to_s + '-' + Time.now.to_i.to_s
|
23
|
+
client = Stomp::Client.new options['broker']
|
24
|
+
|
25
|
+
client.subscribe results, 'auto-delete' => true do |message|
|
26
|
+
results = JSON.parse message.body
|
27
|
+
encoded_output = results['output']
|
28
|
+
decoded_output = Base64.decode64 encoded_output
|
29
|
+
print decoded_output
|
30
|
+
client.close
|
31
|
+
end
|
32
|
+
|
33
|
+
client.publish '/queue/bach', command_json, 'reply-to' => results
|
34
|
+
|
35
|
+
client.join
|
data/bin/bachd
ADDED
@@ -0,0 +1,91 @@
|
|
1
|
+
#! /usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'stomp'
|
4
|
+
require 'json'
|
5
|
+
require 'base64'
|
6
|
+
require 'getoptlong'
|
7
|
+
require 'espeak-ruby'
|
8
|
+
|
9
|
+
class Job
|
10
|
+
include ESpeak
|
11
|
+
|
12
|
+
def serial
|
13
|
+
@serial ||= random_id
|
14
|
+
end
|
15
|
+
|
16
|
+
def random_id
|
17
|
+
[ File.basename($0), Time.now.to_i, rand(1_000_000) ].join '-'
|
18
|
+
end
|
19
|
+
|
20
|
+
def working_directory
|
21
|
+
@working_directory ||= %x[mktemp -d -t #{serial}-XXXXXX].strip
|
22
|
+
end
|
23
|
+
|
24
|
+
def clean_up
|
25
|
+
%x[test -d "#{@working_directory}" && rm -rf "#{@working_directory}"]
|
26
|
+
end
|
27
|
+
|
28
|
+
def hostname
|
29
|
+
%x[hostname].strip
|
30
|
+
end
|
31
|
+
|
32
|
+
def temp_file_name ext = nil
|
33
|
+
File.join working_directory, "#{random_id}#{ext}"
|
34
|
+
end
|
35
|
+
|
36
|
+
attr_accessor :options
|
37
|
+
private :options, :options=
|
38
|
+
|
39
|
+
def initialize options
|
40
|
+
self.options = options
|
41
|
+
end
|
42
|
+
|
43
|
+
def execute
|
44
|
+
sanitize_options!
|
45
|
+
target = temp_file_name '.mp3'
|
46
|
+
espeak target, options
|
47
|
+
raw_data = File.read target
|
48
|
+
encoded_data = Base64.encode64 raw_data
|
49
|
+
{
|
50
|
+
:output => encoded_data,
|
51
|
+
:processor => {
|
52
|
+
:hostname => hostname,
|
53
|
+
:pid => Process.pid
|
54
|
+
}
|
55
|
+
}
|
56
|
+
ensure
|
57
|
+
clean_up
|
58
|
+
end
|
59
|
+
|
60
|
+
def sanitize_options!
|
61
|
+
return if @sanitized_options
|
62
|
+
options['text'] = Base64.decode64 options['text']
|
63
|
+
@sanitized_options = true
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
options = {}
|
68
|
+
argv = GetoptLong.new(
|
69
|
+
[ "--broker", "-b", GetoptLong::OPTIONAL_ARGUMENT ]
|
70
|
+
)
|
71
|
+
argv.each do |option, value|
|
72
|
+
options['broker'] = value if option == '--broker'
|
73
|
+
end
|
74
|
+
options['broker'] ||= 'stomp://127.0.0.1:61613'
|
75
|
+
|
76
|
+
client = Stomp::Client.new options['broker']
|
77
|
+
client.subscribe '/queue/bach' do |message|
|
78
|
+
puts "Received #{message.headers['message-id']}"
|
79
|
+
|
80
|
+
options = JSON.parse message.body
|
81
|
+
results = Job.new(options).execute
|
82
|
+
|
83
|
+
result_json = JSON.generate results
|
84
|
+
destination = message.headers['reply-to']
|
85
|
+
client.publish destination, result_json
|
86
|
+
|
87
|
+
puts "Finished processing #{message.headers['message-id']}"
|
88
|
+
end
|
89
|
+
|
90
|
+
puts "Waiting for clients..."
|
91
|
+
client.join
|
data/lib/bach/version.rb
ADDED
data/lib/constable.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'constable/version'
|
metadata
ADDED
@@ -0,0 +1,76 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: bach
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Craig R Webster
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2011-10-08 00:00:00.000000000Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: stomp
|
16
|
+
requirement: &70362642534600 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *70362642534600
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: espeak-ruby
|
27
|
+
requirement: &70362642533340 !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - ! '>='
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '0'
|
33
|
+
type: :runtime
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: *70362642533340
|
36
|
+
description: Provide a Text-to-Speech service on the service bus
|
37
|
+
email:
|
38
|
+
- craig@barkingiguana.com
|
39
|
+
executables:
|
40
|
+
- bach
|
41
|
+
- bachd
|
42
|
+
extensions: []
|
43
|
+
extra_rdoc_files: []
|
44
|
+
files:
|
45
|
+
- lib/bach/version.rb
|
46
|
+
- lib/constable.rb
|
47
|
+
- bin/bach
|
48
|
+
- bin/bachd
|
49
|
+
- README.md
|
50
|
+
homepage:
|
51
|
+
licenses: []
|
52
|
+
post_install_message:
|
53
|
+
rdoc_options: []
|
54
|
+
require_paths:
|
55
|
+
- lib
|
56
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
63
|
+
none: false
|
64
|
+
requirements:
|
65
|
+
- - ! '>='
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
version: '0'
|
68
|
+
requirements:
|
69
|
+
- A broker capable of talking Stomp
|
70
|
+
- A server with Lame and eSpeak installed
|
71
|
+
rubyforge_project:
|
72
|
+
rubygems_version: 1.8.10
|
73
|
+
signing_key:
|
74
|
+
specification_version: 3
|
75
|
+
summary: Text-to-Speech as a service
|
76
|
+
test_files: []
|