sra2019 0.7.2 → 0.7.3
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 +5 -5
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/lib/sra2019.rb +19 -219
- metadata +11 -72
- metadata.gz.sig +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: f3e1d3453484d6966a4f7b87accbeb853d27ded6f01de06efab200ac453aa096
|
4
|
+
data.tar.gz: bd1cbf03646d9e70e0e01a780bfb402b2daebaf342066f2dd54a9d5bfc4cc9df
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0a86de275c24a13393b6897a12228eb728a9d917605546c545b383c3dd3e9d92d3b519a0663d7256c16b4af757092ae8e36983a26e3523de357bbdca2c93a81f
|
7
|
+
data.tar.gz: 3273e2ab3854b2b1357627099588b11a6ab0991d398e89643388684de17fa9be57b173face08173cb817a4a572c4c15ff6dd2f55884e5b35bf2d7b217f12e2b3
|
checksums.yaml.gz.sig
CHANGED
Binary file
|
data.tar.gz.sig
CHANGED
Binary file
|
data/lib/sra2019.rb
CHANGED
@@ -12,57 +12,13 @@ require 'ostruct'
|
|
12
12
|
require 'subunit'
|
13
13
|
require 'zip/zip'
|
14
14
|
require 'dynarex'
|
15
|
-
require 'ogginfo'
|
16
|
-
require 'wavefile'
|
17
15
|
require 'rxfhelper'
|
18
16
|
require 'wicked_pdf'
|
19
17
|
require 'mini_magick'
|
20
18
|
require 'archive/zip'
|
21
|
-
require 'pollyspeech'
|
22
19
|
require 'rexle-builder'
|
23
20
|
|
24
21
|
|
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
|
-
|
66
22
|
module TimeHelper
|
67
23
|
|
68
24
|
refine String do
|
@@ -79,19 +35,18 @@ module TimeHelper
|
|
79
35
|
|
80
36
|
end
|
81
37
|
|
38
|
+
|
39
|
+
|
82
40
|
class StepsRecorderAnalyser
|
83
41
|
using ColouredText
|
84
42
|
using TimeHelper
|
85
|
-
|
86
|
-
|
43
|
+
|
87
44
|
attr_reader :start_time, :duration
|
88
45
|
attr_accessor :steps
|
89
46
|
|
90
47
|
|
91
48
|
def initialize(s, debug: false, savepath: '/tmp', title: 'Untitled',
|
92
|
-
working_dir: '/tmp'
|
93
|
-
secret_key: nil, voice_id: 'Amy',
|
94
|
-
cache_filepath: '/tmp/pollyspeech/cache'})
|
49
|
+
working_dir: '/tmp')
|
95
50
|
|
96
51
|
@savepath, @title, @working_dir, @debug = savepath, title,
|
97
52
|
working_dir, debug
|
@@ -122,120 +77,9 @@ class StepsRecorderAnalyser
|
|
122
77
|
end
|
123
78
|
|
124
79
|
end
|
125
|
-
|
126
|
-
@pollyspeech = PollySpeech.new(pollyspeech) if pollyspeech[:access_key]
|
127
|
-
|
128
|
-
end
|
129
|
-
|
130
|
-
# adds the audio track to the video file
|
131
|
-
# mp4 in avi out
|
132
|
-
#
|
133
|
-
def add_audio_track(audio_file, video_file, target_video)
|
134
|
-
|
135
|
-
if block_given? then
|
136
|
-
yield(audio_file, video_file, target_video)
|
137
|
-
else
|
138
|
-
`ffmpeg -i #{video_file} -i #{audio_file} -codec copy -shortest #{target_video} -y`
|
139
|
-
end
|
140
|
-
|
141
|
-
end
|
142
|
-
|
143
|
-
# mp4 in mp4 out
|
144
|
-
#
|
145
|
-
def add_subtitles(source, destination)
|
146
|
-
|
147
|
-
|
148
|
-
subtitles = File.join(@working_dir, 's.srt')
|
149
|
-
File.write subtitles, to_srt()
|
150
|
-
|
151
|
-
if block_given? then
|
152
|
-
yield(source, subtitles, destination)
|
153
|
-
else
|
154
|
-
`ffmpeg -i #{source} -i #{subtitles} -c copy -c:s mov_text #{destination} -y`
|
155
|
-
end
|
156
80
|
|
157
81
|
end
|
158
82
|
|
159
|
-
def build_video(source, destination)
|
160
|
-
|
161
|
-
dir = File.dirname(source)
|
162
|
-
file = File.basename(source)
|
163
|
-
|
164
|
-
tidy!
|
165
|
-
|
166
|
-
vid2 = File.join(dir, file.sub(/\.mp4$/,'b\0'))
|
167
|
-
trim_video source, vid2
|
168
|
-
|
169
|
-
vid3 = File.join(dir, file.sub(/\.mp4$/,'c.avi'))
|
170
|
-
|
171
|
-
generate_audio
|
172
|
-
add_audio_track File.join(@working_dir, 'audio.wav'), vid2, vid3
|
173
|
-
|
174
|
-
|
175
|
-
vid4 = File.join(dir, file.sub(/\.avi$/,'d\0'))
|
176
|
-
resize_video vid3, vid4
|
177
|
-
|
178
|
-
vid5 = File.join(dir, file.sub(/\.mp4$/,'e\0'))
|
179
|
-
transcode_video(vid4, vid5)
|
180
|
-
add_subtitles(vid5, destination)
|
181
|
-
|
182
|
-
end
|
183
|
-
|
184
|
-
|
185
|
-
def generate_audio(wav: true)
|
186
|
-
|
187
|
-
return nil unless @pollyspeech
|
188
|
-
|
189
|
-
@steps.each.with_index do |x, i|
|
190
|
-
|
191
|
-
puts 'x.desc: ' + x.desc.inspect if @debug
|
192
|
-
filename = "voice#{i+1}.ogg"
|
193
|
-
|
194
|
-
x.audio = filename
|
195
|
-
file = File.join(@working_dir, filename)
|
196
|
-
@pollyspeech.tts(x.desc.force_encoding('UTF-8'), file)
|
197
|
-
|
198
|
-
x.audio_duration = OggInfo.open(file) {|ogg| ogg.length.to_i }
|
199
|
-
|
200
|
-
if @debug then
|
201
|
-
puts ('x.duration: ' + x.duration.inspect).debug
|
202
|
-
puts ('x.audio_duration: ' + x.audio_duration.inspect).debug
|
203
|
-
end
|
204
|
-
|
205
|
-
duration = x.duration - x.audio_duration
|
206
|
-
x.silence_duration = duration >= 0 ? duration : 0
|
207
|
-
|
208
|
-
if wav then
|
209
|
-
|
210
|
-
silent_file = File.join(@working_dir, "silence#{(i+1).to_s}.wav")
|
211
|
-
puts 'x.silence_duration: ' + x.silence_duration.inspect if @debug
|
212
|
-
wav_silence silent_file, duration: x.silence_duration
|
213
|
-
ogg_to_wav File.join(@working_dir, "voice#{i+1}.ogg")
|
214
|
-
|
215
|
-
end
|
216
|
-
|
217
|
-
sleep 0.02
|
218
|
-
|
219
|
-
end
|
220
|
-
|
221
|
-
if wav then
|
222
|
-
|
223
|
-
intro = File.join(@working_dir, 'intro.wav')
|
224
|
-
wav_silence intro
|
225
|
-
|
226
|
-
files = @steps.length.times.flat_map do |n|
|
227
|
-
[
|
228
|
-
File.join(@working_dir, "voice#{n+1}.wav"),
|
229
|
-
File.join(@working_dir, "silence#{n+1}.wav")
|
230
|
-
]
|
231
|
-
end
|
232
|
-
|
233
|
-
files.prepend intro
|
234
|
-
|
235
|
-
wav_concat files, File.join(@working_dir, 'audio.wav')
|
236
|
-
end
|
237
|
-
|
238
|
-
end
|
239
83
|
|
240
84
|
def import(s)
|
241
85
|
|
@@ -248,11 +92,7 @@ class StepsRecorderAnalyser
|
|
248
92
|
a.each {|n| @steps[n] = nil }
|
249
93
|
@steps.compact!
|
250
94
|
end
|
251
|
-
|
252
|
-
# avi in avi out
|
253
|
-
def resize_video(source, destination)
|
254
|
-
`ffmpeg -i #{source} -vf scale="720:-1" #{destination} -y`
|
255
|
-
end
|
95
|
+
|
256
96
|
|
257
97
|
def tidy!()
|
258
98
|
|
@@ -291,27 +131,7 @@ class StepsRecorderAnalyser
|
|
291
131
|
|
292
132
|
end
|
293
133
|
|
294
|
-
|
295
|
-
|
296
|
-
if block_given? then
|
297
|
-
yield(avi, mp4)
|
298
|
-
else
|
299
|
-
`ffmpeg -i #{avi} #{mp4} -y`
|
300
|
-
end
|
301
|
-
|
302
|
-
end
|
303
|
-
|
304
|
-
def trim_video(video, newvideo)
|
305
|
-
|
306
|
-
start = @steps.first.time - 4
|
307
|
-
t1, t2 = [start, @steps.last.time - 2 ].map do |step|
|
308
|
-
"%02d:%02d:%02d" % (step.to_hms.reverse + [0,0]).take(3).reverse
|
309
|
-
end
|
310
|
-
|
311
|
-
`ffmpeg -i #{video} -ss #{t1} -t #{t2} -async 1 #{newvideo} -y`
|
312
|
-
|
313
|
-
end
|
314
|
-
|
134
|
+
|
315
135
|
# Returns a Dynarex object
|
316
136
|
#
|
317
137
|
def to_dx()
|
@@ -398,43 +218,23 @@ EOF
|
|
398
218
|
@sliml
|
399
219
|
end
|
400
220
|
|
401
|
-
def to_srt(offset=-(@steps.first.time - 2))
|
402
|
-
|
403
|
-
lines = to_subtitles(offset).strip.lines.map.with_index do |x, i|
|
404
|
-
|
405
|
-
raw_times, subtitle = x.split(/ /,2)
|
406
|
-
puts ('raw_times: ' + raw_times.inspect).debug if @debug
|
407
|
-
start_time, end_time = raw_times.split('-',2)
|
408
|
-
times = [("%02d:%02d:%02d,000" % ([0, 0 ] + start_time.split(/\D/)\
|
409
|
-
.map(&:to_i)).reverse.take(3).reverse), \
|
410
|
-
'-->', \
|
411
|
-
("%02d:%02d:%02d,000" % ([0, 0 ] + end_time.split(/\D/).map(&:to_i))\
|
412
|
-
.reverse.take(3).reverse)].join(' ')
|
413
221
|
|
414
|
-
[i+1, times, subtitle].join("\n")
|
415
|
-
|
416
|
-
end
|
417
|
-
|
418
|
-
lines.join("\n")
|
419
|
-
|
420
|
-
end
|
421
222
|
|
422
|
-
def to_subtitles(offset=-(@steps.first.time -
|
423
|
-
|
424
|
-
|
425
|
-
|
426
|
-
|
427
|
-
|
428
|
-
|
429
|
-
|
430
|
-
|
431
|
-
|
432
|
-
|
223
|
+
def to_subtitles(offset=-(@steps.first.time - 1))
|
224
|
+
|
225
|
+
@steps.map do |x|
|
226
|
+
|
227
|
+
secs = x.time.to_i+offset
|
228
|
+
|
229
|
+
if secs < 1 then
|
230
|
+
raise "to_subtitles: time can't be negative. Reduce the offset value"
|
231
|
+
end
|
232
|
+
|
233
|
+
a = Subunit.new(units={minutes:60}, seconds: secs).to_h.to_a
|
234
|
+
time = a.map {|x|"%d%s" % [x[1], x[0][0]] }.join('')
|
235
|
+
"%s %s " % [time, x.desc]
|
433
236
|
|
434
237
|
end
|
435
|
-
|
436
|
-
times.zip(@steps.map(&:desc)).map {|x| x.join(' ')}.join("\n")
|
437
|
-
|
438
238
|
end
|
439
239
|
|
440
240
|
# Writes the steps to a PDF file
|
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.7.
|
4
|
+
version: 0.7.3
|
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-05-
|
38
|
+
date: 2019-05-03 00:00:00.000000000 Z
|
39
39
|
dependencies:
|
40
40
|
- !ruby/object:Gem::Dependency
|
41
41
|
name: hlt
|
@@ -61,82 +61,42 @@ dependencies:
|
|
61
61
|
name: subunit
|
62
62
|
requirement: !ruby/object:Gem::Requirement
|
63
63
|
requirements:
|
64
|
-
- - "~>"
|
65
|
-
- !ruby/object:Gem::Version
|
66
|
-
version: '0.3'
|
67
64
|
- - ">="
|
68
65
|
- !ruby/object:Gem::Version
|
69
66
|
version: 0.3.0
|
70
|
-
type: :runtime
|
71
|
-
prerelease: false
|
72
|
-
version_requirements: !ruby/object:Gem::Requirement
|
73
|
-
requirements:
|
74
67
|
- - "~>"
|
75
68
|
- !ruby/object:Gem::Version
|
76
69
|
version: '0.3'
|
77
|
-
- - ">="
|
78
|
-
- !ruby/object:Gem::Version
|
79
|
-
version: 0.3.0
|
80
|
-
- !ruby/object:Gem::Dependency
|
81
|
-
name: ruby-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
70
|
type: :runtime
|
91
71
|
prerelease: false
|
92
72
|
version_requirements: !ruby/object:Gem::Requirement
|
93
73
|
requirements:
|
94
|
-
- - "~>"
|
95
|
-
- !ruby/object:Gem::Version
|
96
|
-
version: '0.7'
|
97
74
|
- - ">="
|
98
75
|
- !ruby/object:Gem::Version
|
99
|
-
version: 0.
|
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'
|
107
|
-
- - ">="
|
108
|
-
- !ruby/object:Gem::Version
|
109
|
-
version: 1.1.0
|
110
|
-
type: :runtime
|
111
|
-
prerelease: false
|
112
|
-
version_requirements: !ruby/object:Gem::Requirement
|
113
|
-
requirements:
|
76
|
+
version: 0.3.0
|
114
77
|
- - "~>"
|
115
78
|
- !ruby/object:Gem::Version
|
116
|
-
version: '
|
117
|
-
- - ">="
|
118
|
-
- !ruby/object:Gem::Version
|
119
|
-
version: 1.1.0
|
79
|
+
version: '0.3'
|
120
80
|
- !ruby/object:Gem::Dependency
|
121
81
|
name: archive-zip
|
122
82
|
requirement: !ruby/object:Gem::Requirement
|
123
83
|
requirements:
|
124
|
-
- - "~>"
|
125
|
-
- !ruby/object:Gem::Version
|
126
|
-
version: '0.12'
|
127
84
|
- - ">="
|
128
85
|
- !ruby/object:Gem::Version
|
129
86
|
version: 0.12.0
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0.12'
|
130
90
|
type: :runtime
|
131
91
|
prerelease: false
|
132
92
|
version_requirements: !ruby/object:Gem::Requirement
|
133
93
|
requirements:
|
134
|
-
- - "~>"
|
135
|
-
- !ruby/object:Gem::Version
|
136
|
-
version: '0.12'
|
137
94
|
- - ">="
|
138
95
|
- !ruby/object:Gem::Version
|
139
96
|
version: 0.12.0
|
97
|
+
- - "~>"
|
98
|
+
- !ruby/object:Gem::Version
|
99
|
+
version: '0.12'
|
140
100
|
- !ruby/object:Gem::Dependency
|
141
101
|
name: wicked_pdf
|
142
102
|
requirement: !ruby/object:Gem::Requirement
|
@@ -157,26 +117,6 @@ dependencies:
|
|
157
117
|
- - ">="
|
158
118
|
- !ruby/object:Gem::Version
|
159
119
|
version: 1.2.2
|
160
|
-
- !ruby/object:Gem::Dependency
|
161
|
-
name: pollyspeech
|
162
|
-
requirement: !ruby/object:Gem::Requirement
|
163
|
-
requirements:
|
164
|
-
- - "~>"
|
165
|
-
- !ruby/object:Gem::Version
|
166
|
-
version: '0.2'
|
167
|
-
- - ">="
|
168
|
-
- !ruby/object:Gem::Version
|
169
|
-
version: 0.2.0
|
170
|
-
type: :runtime
|
171
|
-
prerelease: false
|
172
|
-
version_requirements: !ruby/object:Gem::Requirement
|
173
|
-
requirements:
|
174
|
-
- - "~>"
|
175
|
-
- !ruby/object:Gem::Version
|
176
|
-
version: '0.2'
|
177
|
-
- - ">="
|
178
|
-
- !ruby/object:Gem::Version
|
179
|
-
version: 0.2.0
|
180
120
|
- !ruby/object:Gem::Dependency
|
181
121
|
name: mini_magick
|
182
122
|
requirement: !ruby/object:Gem::Requirement
|
@@ -223,8 +163,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
223
163
|
- !ruby/object:Gem::Version
|
224
164
|
version: '0'
|
225
165
|
requirements: []
|
226
|
-
|
227
|
-
rubygems_version: 2.5.2.1
|
166
|
+
rubygems_version: 3.0.1
|
228
167
|
signing_key:
|
229
168
|
specification_version: 4
|
230
169
|
summary: Steps Recorder (MS Windows) Analyser 2019
|
metadata.gz.sig
CHANGED
Binary file
|