sra2019 0.6.2 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (6) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +0 -0
  4. data/lib/sra2019.rb +141 -13
  5. metadata +42 -2
  6. metadata.gz.sig +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1bf672d7d472fca296badabb57509cb9559c5cc4140461a4665e68946b009396
4
- data.tar.gz: 3c3c20b141f5f1d972055f78bb961e647d82fe5f12d12492be212c293ac59246
3
+ metadata.gz: 739c20e51f8410fedc1051d860d5f73478101d98961e33e4acbd66fadc1a19b6
4
+ data.tar.gz: d1cc50cf6530199c428d5e7b1dc827015162c4c0a2f8dce5a5f06a327d830208
5
5
  SHA512:
6
- metadata.gz: 3e7b77172be923047220f1b116e09707bab8bdb66016990e900324b16d71b4dca2c61da6db2445de67e55ac12cc8b3f08980c8305c364e6b2e2ff3c6350f9679
7
- data.tar.gz: 4d5ebaba19f49e0dd3ed8fcff0efdefb888bef1c983e8f730bfafd602be05a051932e150dc297a0bbe34bd5bb07bdc4d28e9d34c52342480cabc49d96da766b4
6
+ metadata.gz: b6c6716088a7234cfbdd731eccac19a051463ce8f1629634116442cc64c429d44b7a2967a22820b3a6a3fc2d0c1426b8a036997ee18e45bc3ab206e0ff253839
7
+ data.tar.gz: 852554f94c2df203a024f94adc0bc0345a873dfb0f9f35315e006ab62ca445952b1590f63c805faf43bb682828f98ab3a7d214163535b2ea4c20bf99c3b1bec4
Binary file
data.tar.gz.sig CHANGED
Binary file
@@ -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, :stop_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, debug
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 : tidy(@all_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(steps)
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
- times = @all_steps.map(&:time).each_cons(2).map do |x|
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, hours:60}, seconds: sec).to_h.to_a
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, @stop_time = %w(Start Stop).map do |x|
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.6.2
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-29 00:00:00.000000000 Z
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