sra2019 0.6.2 → 0.7.0
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 +4 -4
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/lib/sra2019.rb +141 -13
- metadata +42 -2
- metadata.gz.sig +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 739c20e51f8410fedc1051d860d5f73478101d98961e33e4acbd66fadc1a19b6
|
4
|
+
data.tar.gz: d1cc50cf6530199c428d5e7b1dc827015162c4c0a2f8dce5a5f06a327d830208
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b6c6716088a7234cfbdd731eccac19a051463ce8f1629634116442cc64c429d44b7a2967a22820b3a6a3fc2d0c1426b8a036997ee18e45bc3ab206e0ff253839
|
7
|
+
data.tar.gz: 852554f94c2df203a024f94adc0bc0345a873dfb0f9f35315e006ab62ca445952b1590f63c805faf43bb682828f98ab3a7d214163535b2ea4c20bf99c3b1bec4
|
checksums.yaml.gz.sig
CHANGED
Binary file
|
data.tar.gz.sig
CHANGED
Binary file
|
data/lib/sra2019.rb
CHANGED
@@ -12,6 +12,8 @@ require 'ostruct'
|
|
12
12
|
require 'subunit'
|
13
13
|
require 'zip/zip'
|
14
14
|
require 'dynarex'
|
15
|
+
require 'ogginfo'
|
16
|
+
require 'wavefile'
|
15
17
|
require 'rxfhelper'
|
16
18
|
require 'wicked_pdf'
|
17
19
|
require 'mini_magick'
|
@@ -20,6 +22,47 @@ require 'pollyspeech'
|
|
20
22
|
require 'rexle-builder'
|
21
23
|
|
22
24
|
|
25
|
+
module WavTool
|
26
|
+
include WaveFile
|
27
|
+
|
28
|
+
def wav_silence(filename, duration: 1)
|
29
|
+
|
30
|
+
square_cycle = [0] * 100 * duration
|
31
|
+
buffer = Buffer.new(square_cycle, Format.new(:mono, :float, 44100))
|
32
|
+
|
33
|
+
Writer.new(filename, Format.new(:mono, :pcm_16, 22050)) do |writer|
|
34
|
+
220.times { writer.write(buffer) }
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
|
39
|
+
def wav_concat(files, save_file='audio.wav')
|
40
|
+
|
41
|
+
Writer.new(save_file, Format.new(:stereo, :pcm_16, 22050)) do |writer|
|
42
|
+
|
43
|
+
files.each do |file_name|
|
44
|
+
|
45
|
+
Reader.new(file_name).each_buffer(samples_per_buffer=4096) do |buffer|
|
46
|
+
writer.write(buffer)
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
53
|
+
|
54
|
+
def ogg_to_wav(oggfile, wavfile=oggfile.sub(/\.ogg$/,'.wav'))
|
55
|
+
|
56
|
+
if block_given? then
|
57
|
+
yield(oggfile)
|
58
|
+
else
|
59
|
+
`oggdec #{oggfile}`
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
65
|
+
|
23
66
|
module TimeHelper
|
24
67
|
|
25
68
|
refine String do
|
@@ -33,14 +76,19 @@ end
|
|
33
76
|
class StepsRecorderAnalyser
|
34
77
|
using ColouredText
|
35
78
|
using TimeHelper
|
79
|
+
include WavTool
|
36
80
|
|
37
|
-
attr_reader :start_time, :
|
81
|
+
attr_reader :start_time, :duration
|
38
82
|
attr_accessor :steps
|
39
83
|
|
40
84
|
|
41
|
-
def initialize(s, debug: false, savepath: '/tmp', title: 'Untitled'
|
85
|
+
def initialize(s, debug: false, savepath: '/tmp', title: 'Untitled',
|
86
|
+
working_dir: '/tmp', pollyspeech: {access_key: nil,
|
87
|
+
secret_key: nil, voice_id: 'Amy',
|
88
|
+
cache_filepath: '/tmp/pollyspeech/cache'})
|
42
89
|
|
43
|
-
@savepath, @title, @debug = savepath, title,
|
90
|
+
@savepath, @title, @working_dir, @debug = savepath, title,
|
91
|
+
working_dir, debug
|
44
92
|
|
45
93
|
raw_content, type = RXFHelper.read(s)
|
46
94
|
|
@@ -56,7 +104,76 @@ class StepsRecorderAnalyser
|
|
56
104
|
@all_steps = parse_steps content
|
57
105
|
@doc = build @all_steps
|
58
106
|
steps = @all_steps.select {|x| x[:user_comment]}
|
59
|
-
@steps = steps.any? ? steps :
|
107
|
+
@steps = steps.any? ? steps : @all_steps
|
108
|
+
|
109
|
+
# find the duration for each step
|
110
|
+
@steps.each.with_index do |x, i|
|
111
|
+
|
112
|
+
x.duration = if i < @steps.length - 1 then
|
113
|
+
@steps[i+1].time - x.time
|
114
|
+
else
|
115
|
+
@duration - x.time
|
116
|
+
end
|
117
|
+
|
118
|
+
end
|
119
|
+
|
120
|
+
@pollyspeech = PollySpeech.new(pollyspeech) if pollyspeech[:access_key]
|
121
|
+
|
122
|
+
end
|
123
|
+
|
124
|
+
# adds the audio track to the video file
|
125
|
+
#
|
126
|
+
def add_audio_track(audio_file, video_file, target_video)
|
127
|
+
|
128
|
+
if block_given? then
|
129
|
+
yield(audio_file, video_file, target_video)
|
130
|
+
else
|
131
|
+
`ffmpeg -i #{video_file} -i #{audio_file} -codec copy -shortest #{target_video}`
|
132
|
+
end
|
133
|
+
|
134
|
+
end
|
135
|
+
|
136
|
+
|
137
|
+
|
138
|
+
def generate_audio(wav: true)
|
139
|
+
|
140
|
+
return nil unless @pollyspeech
|
141
|
+
|
142
|
+
@steps.each.with_index do |x, i|
|
143
|
+
|
144
|
+
puts 'x.desc: ' + x.desc.inspect if @debug
|
145
|
+
filename = "voice#{i+1}.ogg"
|
146
|
+
|
147
|
+
x.audio = filename
|
148
|
+
file = File.join(@working_dir, filename)
|
149
|
+
@pollyspeech.tts(x.desc.force_encoding('UTF-8'), file)
|
150
|
+
|
151
|
+
x.audio_duration = OggInfo.open(file) {|ogg| ogg.length.to_i }
|
152
|
+
x.silence_duration = x.duration - x.audio_duration
|
153
|
+
|
154
|
+
if wav then
|
155
|
+
|
156
|
+
silent_file = File.join(@working_dir, "silence#{(i+1).to_s}.wav")
|
157
|
+
wav_silence silent_file, duration: x.silence_duration
|
158
|
+
ogg_to_wav File.join(@working_dir, "voice#{i+1}.ogg")
|
159
|
+
|
160
|
+
end
|
161
|
+
|
162
|
+
sleep 0.6
|
163
|
+
|
164
|
+
end
|
165
|
+
|
166
|
+
if wav then
|
167
|
+
|
168
|
+
files = @steps.length.times.flat_map do |n|
|
169
|
+
[
|
170
|
+
File.join(@working_dir, "voice#{n+1}.wav"),
|
171
|
+
File.join(@working_dir, "silence#{n+1}.wav")
|
172
|
+
]
|
173
|
+
end
|
174
|
+
|
175
|
+
wav_concat files, File.join(@working_dir, 'audio.wav')
|
176
|
+
end
|
60
177
|
|
61
178
|
end
|
62
179
|
|
@@ -67,14 +184,15 @@ class StepsRecorderAnalyser
|
|
67
184
|
|
68
185
|
end
|
69
186
|
|
70
|
-
def tidy(
|
187
|
+
def tidy!()
|
71
188
|
|
72
189
|
verbose_level = 0
|
73
190
|
|
74
|
-
steps.each do |x|
|
191
|
+
@steps.each do |x|
|
75
192
|
|
76
193
|
x.desc.gsub!(/\s*\([^\)]+\)\s*/,'')
|
77
194
|
x.desc.sub!(/ in "\w+"$/,'')
|
195
|
+
x.desc.sub!(/"User account for [^"]+"/,'the User account icon.')
|
78
196
|
|
79
197
|
if x.desc =~ /User left click/ and verbose_level == 0 then
|
80
198
|
|
@@ -89,6 +207,11 @@ class StepsRecorderAnalyser
|
|
89
207
|
elsif x.desc =~ /User left click/ and verbose_level == 2
|
90
208
|
|
91
209
|
x.desc.sub!(/User left click/, 'Click')
|
210
|
+
verbose_level = 3
|
211
|
+
|
212
|
+
elsif x.desc =~ /User left click/ and verbose_level == 3
|
213
|
+
|
214
|
+
x.desc.sub!(/User left click on/, 'Select')
|
92
215
|
|
93
216
|
else
|
94
217
|
verbose_level = 0
|
@@ -118,7 +241,6 @@ class StepsRecorderAnalyser
|
|
118
241
|
|
119
242
|
def to_kbml(options={})
|
120
243
|
|
121
|
-
|
122
244
|
@doc.xml options
|
123
245
|
|
124
246
|
end
|
@@ -185,9 +307,9 @@ EOF
|
|
185
307
|
@sliml
|
186
308
|
end
|
187
309
|
|
188
|
-
def to_srt()
|
310
|
+
def to_srt(offset=0)
|
189
311
|
|
190
|
-
lines = to_subtitles.strip.lines.map.with_index do |x, i|
|
312
|
+
lines = to_subtitles(offset).strip.lines.map.with_index do |x, i|
|
191
313
|
|
192
314
|
raw_times, subtitle = x.split(/ /,2)
|
193
315
|
|
@@ -206,16 +328,20 @@ EOF
|
|
206
328
|
|
207
329
|
end
|
208
330
|
|
209
|
-
def to_subtitles()
|
331
|
+
def to_subtitles(offset=0)
|
210
332
|
|
211
|
-
|
333
|
+
raw_times = @all_steps.map(&:time)
|
334
|
+
raw_times << raw_times.last + 10
|
335
|
+
|
336
|
+
times = raw_times.each_cons(2).map do |x|
|
212
337
|
|
213
338
|
x.map do |sec|
|
214
|
-
a = Subunit.new(units={minutes:60
|
339
|
+
a = Subunit.new(units={minutes:60}, seconds: sec+offset).to_h.to_a
|
215
340
|
a.map {|x|"%d%s" % [x[1], x[0][0]] }.join('')
|
216
341
|
end.join('-')
|
217
342
|
|
218
343
|
end
|
344
|
+
|
219
345
|
times.zip(@all_steps.map(&:desc)).map {|x| x.join(' ')}.join("\n")
|
220
346
|
|
221
347
|
end
|
@@ -327,12 +453,14 @@ EOF
|
|
327
453
|
puts 'session: ' + session.inspect if @debug
|
328
454
|
puts 'attributes: ' + session.attributes.inspect if @debug
|
329
455
|
|
330
|
-
@start_time,
|
456
|
+
@start_time, stop_time = %w(Start Stop).map do |x|
|
331
457
|
v = session.attributes[(x + 'Time').to_sym]
|
332
458
|
puts 'v: ' + v.inspect if @debug
|
333
459
|
v.to_time
|
334
460
|
end
|
335
461
|
|
462
|
+
@duration = stop_time - @start_time
|
463
|
+
|
336
464
|
session.xpath('EachAction')
|
337
465
|
|
338
466
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sra2019
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.7.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- James Robertson
|
@@ -35,7 +35,7 @@ cert_chain:
|
|
35
35
|
YgXo0DU1HUhuKAAuA0aZdb6DV5BqgZx9e27CLIKqRk5P7TikW49mFaelQfSRi675
|
36
36
|
ugi0V/wkIOHFlKLS87IPnc09
|
37
37
|
-----END CERTIFICATE-----
|
38
|
-
date: 2019-04-
|
38
|
+
date: 2019-04-30 00:00:00.000000000 Z
|
39
39
|
dependencies:
|
40
40
|
- !ruby/object:Gem::Dependency
|
41
41
|
name: hlt
|
@@ -77,6 +77,46 @@ dependencies:
|
|
77
77
|
- - "~>"
|
78
78
|
- !ruby/object:Gem::Version
|
79
79
|
version: '0.3'
|
80
|
+
- !ruby/object:Gem::Dependency
|
81
|
+
name: ogginfo
|
82
|
+
requirement: !ruby/object:Gem::Requirement
|
83
|
+
requirements:
|
84
|
+
- - "~>"
|
85
|
+
- !ruby/object:Gem::Version
|
86
|
+
version: '0.7'
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: 0.7.2
|
90
|
+
type: :runtime
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0.7'
|
97
|
+
- - ">="
|
98
|
+
- !ruby/object:Gem::Version
|
99
|
+
version: 0.7.2
|
100
|
+
- !ruby/object:Gem::Dependency
|
101
|
+
name: wavefile
|
102
|
+
requirement: !ruby/object:Gem::Requirement
|
103
|
+
requirements:
|
104
|
+
- - ">="
|
105
|
+
- !ruby/object:Gem::Version
|
106
|
+
version: 1.1.0
|
107
|
+
- - "~>"
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: '1.1'
|
110
|
+
type: :runtime
|
111
|
+
prerelease: false
|
112
|
+
version_requirements: !ruby/object:Gem::Requirement
|
113
|
+
requirements:
|
114
|
+
- - ">="
|
115
|
+
- !ruby/object:Gem::Version
|
116
|
+
version: 1.1.0
|
117
|
+
- - "~>"
|
118
|
+
- !ruby/object:Gem::Version
|
119
|
+
version: '1.1'
|
80
120
|
- !ruby/object:Gem::Dependency
|
81
121
|
name: archive-zip
|
82
122
|
requirement: !ruby/object:Gem::Requirement
|
metadata.gz.sig
CHANGED
Binary file
|