bach 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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: []
|