viddl 0.0.2
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 +7 -0
- data/LICENSE +13 -0
- data/README.md +100 -0
- data/bin/viddl +80 -0
- data/lib/viddl.rb +19 -0
- data/lib/viddl/system.rb +38 -0
- data/lib/viddl/video.rb +23 -0
- data/lib/viddl/video/clip.rb +129 -0
- data/lib/viddl/video/clip/audio.rb +43 -0
- data/lib/viddl/video/clip/crop.rb +59 -0
- data/lib/viddl/video/clip/cut.rb +83 -0
- data/lib/viddl/video/clip/resize.rb +66 -0
- data/lib/viddl/video/download.rb +49 -0
- data/lib/viddl/video/instance.rb +62 -0
- data/spec/helper.rb +8 -0
- data/spec/system_spec.rb +77 -0
- data/spec/video/clip/audio_spec.rb +81 -0
- data/spec/video/clip/crop_spec.rb +113 -0
- data/spec/video/clip/cut_spec.rb +246 -0
- data/spec/video/clip/resize_spec.rb +136 -0
- data/spec/video/clip_spec.rb +443 -0
- data/spec/video/download_spec.rb +42 -0
- data/spec/video/instance_spec.rb +121 -0
- data/spec/video_spec.rb +24 -0
- metadata +109 -0
@@ -0,0 +1,443 @@
|
|
1
|
+
require "helper"
|
2
|
+
|
3
|
+
describe Viddl::Video::Clip do
|
4
|
+
|
5
|
+
before(:each) do
|
6
|
+
@source_file = "/tmp/6g4dkBF5anU.mkv"
|
7
|
+
@clip = Viddl::Video::Clip.new(@source_file)
|
8
|
+
end
|
9
|
+
|
10
|
+
context "#process" do
|
11
|
+
|
12
|
+
context "with no options" do
|
13
|
+
|
14
|
+
it "execs command line" do
|
15
|
+
@options = {}
|
16
|
+
expect(Kernel).to receive(:system)
|
17
|
+
@result = @clip.send(:process, @options)
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
|
22
|
+
context "cut options" do
|
23
|
+
|
24
|
+
context "with duration" do
|
25
|
+
|
26
|
+
it "execs command line" do
|
27
|
+
@options = {
|
28
|
+
duration: 12
|
29
|
+
}
|
30
|
+
expect(Kernel).to receive(:system)
|
31
|
+
@result = @clip.send(:process, @options)
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
|
36
|
+
context "with start time and duration" do
|
37
|
+
|
38
|
+
it "execs command line" do
|
39
|
+
@options = {
|
40
|
+
start: 10,
|
41
|
+
duration: 15
|
42
|
+
}
|
43
|
+
expect(Kernel).to receive(:system)
|
44
|
+
@result = @clip.send(:process, @options)
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
|
49
|
+
context "with start and end time" do
|
50
|
+
|
51
|
+
it "execs command line" do
|
52
|
+
@options = {
|
53
|
+
start: 8,
|
54
|
+
end: 15
|
55
|
+
}
|
56
|
+
expect(Kernel).to receive(:system)
|
57
|
+
@result = @clip.send(:process, @options)
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
61
|
+
|
62
|
+
context "with start, end time and duration" do
|
63
|
+
|
64
|
+
it "raises" do
|
65
|
+
@options = {
|
66
|
+
duration: 5,
|
67
|
+
end: 15,
|
68
|
+
start: 10
|
69
|
+
}
|
70
|
+
expect {
|
71
|
+
@clip.send(:process, @options)
|
72
|
+
}.to(raise_error(RuntimeError))
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
76
|
+
|
77
|
+
end
|
78
|
+
|
79
|
+
end
|
80
|
+
|
81
|
+
context "#command_line" do
|
82
|
+
|
83
|
+
context "with no options" do
|
84
|
+
|
85
|
+
before(:each) do
|
86
|
+
@options = {}
|
87
|
+
@result = @clip.send(:command_line, @options)
|
88
|
+
end
|
89
|
+
|
90
|
+
it "includes file name" do
|
91
|
+
expect(@result).to(include(@source_file))
|
92
|
+
end
|
93
|
+
|
94
|
+
it "has no time args" do
|
95
|
+
expect(@result).to_not(include("-ss"))
|
96
|
+
expect(@result).to_not(include("-t"))
|
97
|
+
end
|
98
|
+
|
99
|
+
it "has no audio off option" do
|
100
|
+
expect(@result).to_not(include("-an"))
|
101
|
+
end
|
102
|
+
|
103
|
+
end
|
104
|
+
|
105
|
+
context "with audio = false" do
|
106
|
+
|
107
|
+
before(:each) do
|
108
|
+
@options = {
|
109
|
+
audio: false
|
110
|
+
}
|
111
|
+
@result = @clip.send(:command_line, @options)
|
112
|
+
end
|
113
|
+
|
114
|
+
it "includes file name" do
|
115
|
+
expect(@result).to(include(@source_file))
|
116
|
+
end
|
117
|
+
|
118
|
+
it "has duration" do
|
119
|
+
expect(@result).to(include("-an"))
|
120
|
+
end
|
121
|
+
|
122
|
+
end
|
123
|
+
|
124
|
+
context "with crop options" do
|
125
|
+
|
126
|
+
context "incomplete" do
|
127
|
+
|
128
|
+
it "raises" do
|
129
|
+
@options = {
|
130
|
+
crop: {
|
131
|
+
x: 1
|
132
|
+
}
|
133
|
+
}
|
134
|
+
expect {
|
135
|
+
@clip.send(:command_line, @options)
|
136
|
+
}.to(raise_error(RuntimeError))
|
137
|
+
end
|
138
|
+
|
139
|
+
end
|
140
|
+
|
141
|
+
context "valid" do
|
142
|
+
|
143
|
+
before(:each) do
|
144
|
+
@options = {
|
145
|
+
crop: {
|
146
|
+
x: 150,
|
147
|
+
y: 160,
|
148
|
+
width: 170,
|
149
|
+
height: 180
|
150
|
+
}
|
151
|
+
}
|
152
|
+
@result = @clip.send(:command_line, @options)
|
153
|
+
end
|
154
|
+
|
155
|
+
it "has correct scale arg" do
|
156
|
+
expect(@result).to(include("-vf"))
|
157
|
+
expect(@result).to(include("crop=170:180:150:160"))
|
158
|
+
end
|
159
|
+
|
160
|
+
end
|
161
|
+
|
162
|
+
end
|
163
|
+
|
164
|
+
context "with resize options" do
|
165
|
+
|
166
|
+
context "with width only" do
|
167
|
+
|
168
|
+
before(:each) do
|
169
|
+
@options = {
|
170
|
+
width: 1024
|
171
|
+
}
|
172
|
+
@result = @clip.send(:command_line, @options)
|
173
|
+
end
|
174
|
+
|
175
|
+
it "has correct scale arg" do
|
176
|
+
expect(@result).to(include("-vf"))
|
177
|
+
expect(@result).to(include("scale=1024:-1"))
|
178
|
+
end
|
179
|
+
|
180
|
+
end
|
181
|
+
|
182
|
+
context "with height only" do
|
183
|
+
|
184
|
+
before(:each) do
|
185
|
+
@options = {
|
186
|
+
height: 768
|
187
|
+
}
|
188
|
+
@result = @clip.send(:command_line, @options)
|
189
|
+
end
|
190
|
+
|
191
|
+
it "has correct scale arg" do
|
192
|
+
expect(@result).to(include("-vf"))
|
193
|
+
expect(@result).to(include("scale=-1:768"))
|
194
|
+
end
|
195
|
+
|
196
|
+
end
|
197
|
+
|
198
|
+
context "with width and height" do
|
199
|
+
|
200
|
+
before(:each) do
|
201
|
+
@options = {
|
202
|
+
width: 1920,
|
203
|
+
height: 1280
|
204
|
+
}
|
205
|
+
@result = @clip.send(:command_line, @options)
|
206
|
+
end
|
207
|
+
|
208
|
+
it "has correct scale arg" do
|
209
|
+
expect(@result).to(include("-vf"))
|
210
|
+
expect(@result).to(include("scale=1920:1280"))
|
211
|
+
end
|
212
|
+
|
213
|
+
end
|
214
|
+
|
215
|
+
end
|
216
|
+
|
217
|
+
context "with cut options" do
|
218
|
+
|
219
|
+
context "with duration" do
|
220
|
+
|
221
|
+
before(:each) do
|
222
|
+
@options = {
|
223
|
+
duration: 12
|
224
|
+
}
|
225
|
+
@result = @clip.send(:command_line, @options)
|
226
|
+
end
|
227
|
+
|
228
|
+
it "includes file name" do
|
229
|
+
expect(@result).to(include(@source_file))
|
230
|
+
end
|
231
|
+
|
232
|
+
it "has duration" do
|
233
|
+
expect(@result).to_not(include("-ss"))
|
234
|
+
expect(@result).to(include("-t 12"))
|
235
|
+
end
|
236
|
+
|
237
|
+
end
|
238
|
+
|
239
|
+
context "with start time and duration" do
|
240
|
+
|
241
|
+
before(:each) do
|
242
|
+
@options = {
|
243
|
+
start: 10,
|
244
|
+
duration: 15
|
245
|
+
}
|
246
|
+
@result = @clip.send(:command_line, @options)
|
247
|
+
end
|
248
|
+
|
249
|
+
it "includes file name" do
|
250
|
+
expect(@result).to(include(@source_file))
|
251
|
+
end
|
252
|
+
|
253
|
+
it "has duration and start time" do
|
254
|
+
expect(@result).to(include("-ss 10"))
|
255
|
+
expect(@result).to(include("-t 15"))
|
256
|
+
end
|
257
|
+
|
258
|
+
end
|
259
|
+
|
260
|
+
context "with start and end time" do
|
261
|
+
|
262
|
+
before(:each) do
|
263
|
+
@options = {
|
264
|
+
start: 8,
|
265
|
+
end: 15
|
266
|
+
}
|
267
|
+
@result = @clip.send(:command_line, @options)
|
268
|
+
end
|
269
|
+
|
270
|
+
it "includes file name" do
|
271
|
+
expect(@result).to(include(@source_file))
|
272
|
+
end
|
273
|
+
|
274
|
+
it "has duration and start time" do
|
275
|
+
expect(@result).to(include("-ss 8"))
|
276
|
+
expect(@result).to(include("-t 7"))
|
277
|
+
end
|
278
|
+
|
279
|
+
end
|
280
|
+
|
281
|
+
context "with start, end time and duration" do
|
282
|
+
|
283
|
+
it "raises" do
|
284
|
+
@options = {
|
285
|
+
duration: 5,
|
286
|
+
end: 15,
|
287
|
+
start: 10
|
288
|
+
}
|
289
|
+
expect {
|
290
|
+
@clip.send(:command_line, @options)
|
291
|
+
}.to(raise_error(RuntimeError))
|
292
|
+
end
|
293
|
+
|
294
|
+
end
|
295
|
+
|
296
|
+
end
|
297
|
+
|
298
|
+
end
|
299
|
+
|
300
|
+
context "#output_path" do
|
301
|
+
|
302
|
+
context "with no options" do
|
303
|
+
|
304
|
+
it "matches source path file name" do
|
305
|
+
path = @clip.send(:output_path)
|
306
|
+
expect(path).to(eq("6g4dkBF5anU.mkv"))
|
307
|
+
end
|
308
|
+
|
309
|
+
end
|
310
|
+
|
311
|
+
context "crop options" do
|
312
|
+
|
313
|
+
context "valid" do
|
314
|
+
|
315
|
+
it "has crop options in filename" do
|
316
|
+
options = {
|
317
|
+
crop: {
|
318
|
+
x: 200,
|
319
|
+
y: 210,
|
320
|
+
width: 220,
|
321
|
+
height: 230
|
322
|
+
}
|
323
|
+
}
|
324
|
+
path = @clip.send(:output_path, options)
|
325
|
+
expect(path).to(eq("6g4dkBF5anU-cx200cy210cw220ch230.mkv"))
|
326
|
+
end
|
327
|
+
|
328
|
+
end
|
329
|
+
|
330
|
+
end
|
331
|
+
|
332
|
+
context "resize options" do
|
333
|
+
|
334
|
+
context "with width only" do
|
335
|
+
|
336
|
+
it "has width" do
|
337
|
+
options = {
|
338
|
+
width: 640
|
339
|
+
}
|
340
|
+
path = @clip.send(:output_path, options)
|
341
|
+
expect(path).to(eq("6g4dkBF5anU-w640.mkv"))
|
342
|
+
end
|
343
|
+
|
344
|
+
end
|
345
|
+
|
346
|
+
context "with height only" do
|
347
|
+
|
348
|
+
it "has width" do
|
349
|
+
options = {
|
350
|
+
height: 480
|
351
|
+
}
|
352
|
+
path = @clip.send(:output_path, options)
|
353
|
+
expect(path).to(eq("6g4dkBF5anU-h480.mkv"))
|
354
|
+
end
|
355
|
+
|
356
|
+
end
|
357
|
+
|
358
|
+
context "with width and height" do
|
359
|
+
|
360
|
+
it "has width" do
|
361
|
+
options = {
|
362
|
+
width: 1280,
|
363
|
+
height: 720
|
364
|
+
}
|
365
|
+
path = @clip.send(:output_path, options)
|
366
|
+
expect(path).to(eq("6g4dkBF5anU-w1280h720.mkv"))
|
367
|
+
end
|
368
|
+
|
369
|
+
end
|
370
|
+
|
371
|
+
end
|
372
|
+
|
373
|
+
context "with no audio" do
|
374
|
+
|
375
|
+
it "has no audio option" do
|
376
|
+
options = {
|
377
|
+
audio: false
|
378
|
+
}
|
379
|
+
path = @clip.send(:output_path, options)
|
380
|
+
expect(path).to(eq("6g4dkBF5anU-noaudio.mkv"))
|
381
|
+
end
|
382
|
+
|
383
|
+
end
|
384
|
+
|
385
|
+
context "cut options" do
|
386
|
+
|
387
|
+
context "with start time" do
|
388
|
+
|
389
|
+
it "matches source path file name" do
|
390
|
+
options = {
|
391
|
+
audio: true,
|
392
|
+
start: 10
|
393
|
+
}
|
394
|
+
path = @clip.send(:output_path, options)
|
395
|
+
expect(path).to(eq("6g4dkBF5anU-s10.mkv"))
|
396
|
+
end
|
397
|
+
|
398
|
+
end
|
399
|
+
|
400
|
+
context "with duration" do
|
401
|
+
|
402
|
+
it "matches source path file name" do
|
403
|
+
options = {
|
404
|
+
audio: true,
|
405
|
+
duration: 1.5
|
406
|
+
}
|
407
|
+
path = @clip.send(:output_path, options)
|
408
|
+
expect(path).to(eq("6g4dkBF5anU-d1.5.mkv"))
|
409
|
+
end
|
410
|
+
|
411
|
+
end
|
412
|
+
|
413
|
+
context "with start time and duration" do
|
414
|
+
|
415
|
+
it "matches source path file name" do
|
416
|
+
options = {
|
417
|
+
audio: true,
|
418
|
+
duration: 12,
|
419
|
+
start: 6
|
420
|
+
}
|
421
|
+
path = @clip.send(:output_path, options)
|
422
|
+
expect(path).to(eq("6g4dkBF5anU-s6d12.mkv"))
|
423
|
+
end
|
424
|
+
|
425
|
+
end
|
426
|
+
|
427
|
+
end
|
428
|
+
|
429
|
+
end
|
430
|
+
|
431
|
+
context "#options_formatted" do
|
432
|
+
|
433
|
+
it "formats options for each module" do
|
434
|
+
options = {}
|
435
|
+
expect(Viddl::Video::Clip::Audio).to(receive(:options_formatted).and_return({}))
|
436
|
+
expect(Viddl::Video::Clip::Cut).to(receive(:options_formatted).and_return({}))
|
437
|
+
expect(Viddl::Video::Clip::Resize).to(receive(:options_formatted).and_return({}))
|
438
|
+
@clip.send(:options_formatted, options)
|
439
|
+
end
|
440
|
+
|
441
|
+
end
|
442
|
+
|
443
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require "helper"
|
2
|
+
|
3
|
+
describe Viddl::Video::Download do
|
4
|
+
|
5
|
+
before(:each) do
|
6
|
+
@video_id = "6g4dkBF5anU"
|
7
|
+
@source_url = "https://youtube.com/watch?v=#{@video_id}"
|
8
|
+
@video = Viddl::Video::Instance.new(@source_url)
|
9
|
+
@download = Viddl::Video::Download.new(@video)
|
10
|
+
end
|
11
|
+
|
12
|
+
context "#process" do
|
13
|
+
|
14
|
+
context "with no options" do
|
15
|
+
|
16
|
+
it "execs command line" do
|
17
|
+
@options = {}
|
18
|
+
expect(Kernel).to(receive(:system).and_return(true))
|
19
|
+
@result = @download.send(:process, @options)
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
|
26
|
+
context "#command_line" do
|
27
|
+
|
28
|
+
before(:each) do
|
29
|
+
@result = @download.send(:command_line)
|
30
|
+
end
|
31
|
+
|
32
|
+
it "includes url" do
|
33
|
+
expect(@result).to(include(@source_url))
|
34
|
+
end
|
35
|
+
|
36
|
+
it "includes temp file path" do
|
37
|
+
expect(@result).to(include("#{Viddl::Video::Download::TEMPDIR}/#{@video_id}"))
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|