bach 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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
@@ -0,0 +1,3 @@
1
+ module Bach
2
+ VERSION = '0.0.1'
3
+ end
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: []