viddl 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 754721cccbe03abc4baaaeeb3cc7b4a466ff792b
4
+ data.tar.gz: 4aaddeaa7ff0dcd5bdedd75e81168671a640e528
5
+ SHA512:
6
+ metadata.gz: d0ac5e272ff2b62a0db0e2de646c85450ad802a1b9248216966f1421a3fdcaa555ca4938c867629bc09756945915f787e59976195147852941bc0823cc1ac5c8
7
+ data.tar.gz: 81f1c6314ab103b92c6bead41880835dc5eb4afebe9362d09f6881d35cc9fb4122b8b82604745b426364dfe7ec8d410ce14fa1f725d965e696451fa4d143fd8f
data/LICENSE ADDED
@@ -0,0 +1,13 @@
1
+ Copyright 2017 Ari Russo
2
+
3
+ Licensed under the Apache License, Version 2.0 (the "License");
4
+ you may not use this file except in compliance with the License.
5
+ You may obtain a copy of the License at
6
+
7
+ http://www.apache.org/licenses/LICENSE-2.0
8
+
9
+ Unless required by applicable law or agreed to in writing, software
10
+ distributed under the License is distributed on an "AS IS" BASIS,
11
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ See the License for the specific language governing permissions and
13
+ limitations under the License.
data/README.md ADDED
@@ -0,0 +1,100 @@
1
+ # Viddl
2
+
3
+ ![Viddl](http://i.imgur.com/OuHviqv.png "Viddl")
4
+
5
+ Use Viddl to quickly download, cut, crop and resize videos
6
+
7
+ Viddl can be used at the [command line](#command-line) or in [Ruby](#ruby)
8
+
9
+ It requires that both [youtube-dl](https://github.com/rg3/youtube-dl) and [ffmpeg](https://ffmpeg.org) are installed before using.
10
+
11
+ ## Usage
12
+
13
+ Running Viddl generates video clip files in the current directory
14
+
15
+ ### Command Line
16
+
17
+ The command line usage and options are as follows:
18
+
19
+ #### Download
20
+
21
+ With no options, Viddl will download the original video
22
+
23
+ ```sh
24
+ viddl https://www.youtube.com/watch?v=6g4dkBF5anU
25
+ ```
26
+
27
+ #### Cut
28
+
29
+ This will start the clip at 10 seconds into the original video and run for five seconds
30
+
31
+ ```sh
32
+ viddl https://www.youtube.com/watch?v=6g4dkBF5anU -s 10 -d 5
33
+ ```
34
+
35
+ Alternately, this will start the clip at 15 seconds in the original video and stop at 22 seconds
36
+
37
+ ```sh
38
+ viddl https://www.youtube.com/watch?v=6g4dkBF5anU -s 15 -e 22
39
+ ```
40
+
41
+ #### Resize
42
+
43
+ This will resize to 640 x 480:
44
+
45
+ ```sh
46
+ viddl https://www.youtube.com/watch?v=6g4dkBF5anU -w 640 -h 480
47
+ ```
48
+
49
+ #### Crop
50
+
51
+ This will crop a 40 x 40 pixel box at position 20 x 20:
52
+
53
+ ```sh
54
+ viddl https://www.youtube.com/watch?v=6g4dkBF5anU --cx 20 --cy 20 --cw 40 --ch 40
55
+ ```
56
+
57
+ #### Strip Audio
58
+
59
+ Audio can be left out of the clip:
60
+
61
+ ```sh
62
+ viddl https://www.youtube.com/watch?v=6g4dkBF5anU --no-audio
63
+ ```
64
+
65
+ #### Combine
66
+
67
+ Any or all of these options can be used together:
68
+
69
+ ```sh
70
+ viddl https://www.youtube.com/watch?v=6g4dkBF5anU -s 15 -e 22 --no-audio --cx 20 --cy 20 --cw 40 --ch 40 -w 640 -h 480
71
+ ```
72
+
73
+ ### Ruby
74
+
75
+ Similar to the command line, Ruby usage and options are as follows:
76
+
77
+ ```ruby
78
+ options = {
79
+ start: 15,
80
+ end: 22,
81
+ audio: false,
82
+ crop: {
83
+ x: 20,
84
+ y: 20,
85
+ width: 40,
86
+ height: 40
87
+ },
88
+ width: 640,
89
+ height: 480
90
+ }
91
+
92
+ video = Viddl::Video.download("https://www.youtube.com/watch?v=6g4dkBF5anU")
93
+ video.create_clip(options)
94
+ ```
95
+
96
+ ## License
97
+
98
+ Licensed under Apache 2.0, See the file LICENSE
99
+
100
+ Copyright (c) 2017 [Ari Russo](http://arirusso.com)
data/bin/viddl ADDED
@@ -0,0 +1,80 @@
1
+ #!/usr/bin/env ruby
2
+ $LOAD_PATH.unshift File.join(File.dirname(__FILE__), '..', 'lib')
3
+
4
+ require "optparse"
5
+ require "viddl"
6
+
7
+ def help(opts)
8
+ puts(opts)
9
+ exit
10
+ end
11
+
12
+ options = {}
13
+ opts = OptionParser.new do |opts|
14
+ opts.banner = "Usage: viddl [url] [options]"
15
+
16
+ ## cut
17
+
18
+ opts.on("-dDURATION", "--duration=DURATION", "Duration") do |duration|
19
+ options[:duration] = duration.to_f
20
+ end
21
+
22
+ opts.on("-eEND", "--end=END", "End time") do |en|
23
+ options[:end] = en.to_f
24
+ end
25
+
26
+ opts.on("-sSTART", "--start=START", "Start time") do |start|
27
+ options[:start] = start.to_f
28
+ end
29
+
30
+ # resize
31
+
32
+ opts.on("-wWIDTH", "--width=WIDTH", "Width") do |width|
33
+ options[:width] = width.to_i
34
+ end
35
+
36
+ opts.on("-hHEIGHT", "--height=HEIGHT", "Height") do |height|
37
+ options[:height] = height.to_i
38
+ end
39
+
40
+ # crop
41
+
42
+ opts.on("--cx=CX", "Crop X") do |cx|
43
+ options[:crop] ||= {}
44
+ options[:crop][:x] = cx.to_i
45
+ end
46
+
47
+ opts.on("--cy=CY", "Crop Y") do |cy|
48
+ options[:crop] ||= {}
49
+ options[:crop][:y] = cy.to_i
50
+ end
51
+
52
+ opts.on("--cw=CWIDTH", "Crop Width") do |cwidth|
53
+ options[:crop] ||= {}
54
+ options[:crop][:width] = cwidth.to_i
55
+ end
56
+
57
+ opts.on("--ch=CHEIGHT", "Crop Height") do |cheight|
58
+ options[:crop] ||= {}
59
+ options[:crop][:height] = cheight.to_i
60
+ end
61
+
62
+ # audio
63
+
64
+ opts.on("--no-audio", "No audio") do
65
+ options[:audio] = false
66
+ end
67
+
68
+ opts.on_tail("--help", "Show this message") { help(opts) }
69
+
70
+ end
71
+ opts.parse!
72
+
73
+ url = ARGV[0]
74
+
75
+ if url.nil?
76
+ help(opts) and exit
77
+ end
78
+
79
+ video = Viddl::Video.download(url)
80
+ video.create_clip(options)
data/lib/viddl.rb ADDED
@@ -0,0 +1,19 @@
1
+ #
2
+ # viddl
3
+ #
4
+ # (c)2017 Ari Russo
5
+ # Apache 2.0 License
6
+ # https://github.com/arirusso/viddl
7
+ #
8
+
9
+ # modules
10
+ require "viddl/system"
11
+ require "viddl/video"
12
+
13
+ module Viddl
14
+
15
+ extend self
16
+
17
+ VERSION = "0.0.2"
18
+
19
+ end
@@ -0,0 +1,38 @@
1
+ module Viddl
2
+
3
+ module System
4
+
5
+ extend self
6
+
7
+ # Validate that the system has all of its dependencies
8
+ # @return [Boolean]
9
+ def validate
10
+ validate_ffmpeg
11
+ validate_youtube_dl
12
+ true
13
+ end
14
+
15
+ private
16
+
17
+ # Validate that ffmpeg is installed
18
+ # @return [Boolean]
19
+ def validate_ffmpeg
20
+ result = Kernel.system("ffmpeg")
21
+ if result.nil?
22
+ raise("Viddl requires that ffmpeg be installed")
23
+ end
24
+ true
25
+ end
26
+
27
+ # Validate that youtube-dl is installed
28
+ # @return [Boolean]
29
+ def validate_youtube_dl
30
+ result = Kernel.system("youtube-dl")
31
+ if result.nil?
32
+ raise("Viddl requires that youtube-dl be installed https://github.com/rg3/youtube-dl")
33
+ end
34
+ end
35
+
36
+ end
37
+
38
+ end
@@ -0,0 +1,23 @@
1
+ require "viddl/video/clip"
2
+ require "viddl/video/download"
3
+ require "viddl/video/instance"
4
+
5
+ module Viddl
6
+
7
+ module Video
8
+
9
+ extend self
10
+
11
+ # Download a video using the given url
12
+ # @param [String] url
13
+ # @param [Hash] options
14
+ # @return [Video::Instance]
15
+ def download(url, options = {})
16
+ video = Instance.new(url)
17
+ video.process_download(options)
18
+ video
19
+ end
20
+
21
+ end
22
+
23
+ end
@@ -0,0 +1,129 @@
1
+ require "viddl/video/clip/audio"
2
+ require "viddl/video/clip/crop"
3
+ require "viddl/video/clip/cut"
4
+ require "viddl/video/clip/resize"
5
+
6
+ module Viddl
7
+
8
+ module Video
9
+
10
+ class Clip
11
+
12
+ MODULES = [Audio, Crop, Cut, Resize]
13
+
14
+ # Create a clip using the given video source file path and options
15
+ # @param [String] source_path Path to video file to create clip from
16
+ # @param [Hash] options
17
+ # @option options [Boolean] :audio Whether to include audio
18
+ # @option options [Numeric] :start Time in the source file where the clip starts
19
+ # @option options [Numeric] :duration Duration of the clip
20
+ # @option options [Numeric] :end Time in the source file where the clip ends
21
+ # @option options [Integer, String] :width The desired width to resize to
22
+ # @option options [Integer, String] :height The desired height to resize to
23
+ # @option options [Hash] :crop The desired crop parameters (:x, :y, :width, :height)
24
+ # @return [Clip]
25
+ def self.process(path, options = {})
26
+ clip = new(path)
27
+ clip.process(options)
28
+ clip
29
+ end
30
+
31
+ # @param [String] source_path Path to video file to create clip from
32
+ def initialize(source_path)
33
+ @source_path = source_path
34
+ end
35
+
36
+ # Create a clip using the given options
37
+ # @param [Hash] options
38
+ # @option options [Boolean] :audio Whether to include audio
39
+ # @option options [Numeric] :start Time in the source file where the clip starts
40
+ # @option options [Numeric] :duration Duration of the clip
41
+ # @option options [Numeric] :end Time in the source file where the clip ends
42
+ # @option options [Integer, String] :width The desired width to resize to
43
+ # @option options [Integer, String] :height The desired height to resize to
44
+ # @option options [Hash] :crop The desired crop parameters (:x, :y, :width, :height)
45
+ # @return [Boolean]
46
+ def process(options = {})
47
+ command = command_line(options)
48
+ Kernel.system(command)
49
+ end
50
+
51
+ private
52
+
53
+ # Command line to create a clip from the source file and given options
54
+ # @param [Hash] options
55
+ # @option options [Boolean] :audio Whether to include audio
56
+ # @option options [Numeric] :start Time in the source file where the clip starts
57
+ # @option options [Numeric] :duration Duration of the clip
58
+ # @option options [Numeric] :end Time in the source file where the clip ends
59
+ # @option options [Integer, String] :width The desired width to resize to
60
+ # @option options [Integer, String] :height The desired height to resize to
61
+ # @option options [Hash] :crop The desired crop parameters (:x, :y, :width, :height)
62
+ # @return [String]
63
+ def command_line(options = {})
64
+ if options.values.compact.empty?
65
+ # when there are no clip options, the source file can just be copied
66
+ # over to the output file location without using ffmpeg
67
+ "cp #{@source_path} #{output_path}"
68
+ else
69
+ formatted_opts = options_formatted(options)
70
+
71
+ modules_with_args = MODULES.select { |mod| mod.respond_to?(:args) }
72
+ modules_with_filters = MODULES.select { |mod| mod.respond_to?(:filter_args) }
73
+
74
+ module_args = modules_with_args.map { |mod| mod.args(formatted_opts) }.compact
75
+ module_filters = modules_with_filters.map { |mod| mod.filter_args(formatted_opts) }.compact
76
+
77
+ module_arg_string = module_args.join(" ")
78
+ unless module_filters.empty?
79
+ module_arg_string += " -vf '#{module_filters.join(",")}'"
80
+ end
81
+
82
+ "ffmpeg -i #{@source_path} #{module_arg_string} #{output_path(formatted_opts)}"
83
+ end
84
+ end
85
+
86
+ # Options formatted for ffmpeg
87
+ # @param [Hash] options
88
+ # @option options [Boolean] :audio Whether to include audio (default: true)
89
+ # @option options [Numeric] :start Time in the source file where the clip starts
90
+ # @option options [Numeric] :duration Duration of the clip
91
+ # @option options [Numeric] :end Time in the source file where the clip ends
92
+ # @option options [Integer, String] :width The desired width to resize to
93
+ # @option options [Integer, String] :height The desired height to resize to
94
+ # @option options [Hash] :crop The desired crop parameters (:x, :y, :width, :height)
95
+ # @return [Hash]
96
+ def options_formatted(options = {})
97
+ mod_options = MODULES.map { |mod| mod.options_formatted(options) }
98
+ mod_options.inject(:merge)
99
+ end
100
+
101
+ # Path of the created clip
102
+ # @param [Hash] options
103
+ # @option options [Boolean] :audio Whether to include audio
104
+ # @option options [Numeric] :start Time in the source file where the clip starts
105
+ # @option options [Numeric] :duration Duration of the clip
106
+ # @option options [Integer, String] :width The desired width to resize to
107
+ # @option options [Integer, String] :height The desired height to resize to
108
+ # @option options [Hash] :crop The desired crop parameters (:x, :y, :width, :height)
109
+ # @return [String]
110
+ def output_path(options = {})
111
+ base = @source_path.scan(/#{Download::TEMPDIR}\/(.*)/).flatten.first
112
+ result = base
113
+ if !options.values.flatten.compact.empty?
114
+ name, ext = *base.split(".")
115
+ tokens = ""
116
+ MODULES.each do |mod|
117
+ token = mod.filename_token(options)
118
+ tokens += "-#{token}" unless token.nil?
119
+ end
120
+ result = "#{name}#{tokens}.#{ext}"
121
+ end
122
+ result
123
+ end
124
+
125
+ end
126
+
127
+ end
128
+
129
+ end
@@ -0,0 +1,43 @@
1
+ module Viddl
2
+
3
+ module Video
4
+
5
+ class Clip
6
+
7
+ module Audio
8
+
9
+ extend self
10
+
11
+ # Audio options formatted for ffmpeg
12
+ # @param [Hash] options
13
+ # @option options [Boolean] :audio Whether to include audio (default: true)
14
+ # @return [Hash]
15
+ def options_formatted(options = {})
16
+ result = {}
17
+ result[:audio] = !options[:audio].eql?(false)
18
+ result
19
+ end
20
+
21
+ # Command line options for audio
22
+ # @param [Hash] options
23
+ # @option options [Boolean] :audio Whether to include audio (default: false)
24
+ # @return [String, nil]
25
+ def args(options = {})
26
+ "-an" if options[:audio].eql?(false)
27
+ end
28
+
29
+ # Token added to clip filename for audio args
30
+ # @param [Hash] options
31
+ # @option options [Boolean] :audio Whether to include audio in the clip (default: false)
32
+ # @return [String, nil]
33
+ def filename_token(options = {})
34
+ "noaudio" if options[:audio].eql?(false)
35
+ end
36
+
37
+ end
38
+
39
+ end
40
+
41
+ end
42
+
43
+ end