sra2019 0.7.2 → 0.7.3
Sign up to get free protection for your applications and to get access to all the features.
- 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
|