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 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: []