video_converter 0.6.14 → 0.7.0
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/lib/video_converter/base.rb +15 -11
- data/lib/video_converter/command.rb +1 -1
- data/lib/video_converter/f4fpackager.rb +68 -0
- data/lib/video_converter/input.rb +1 -4
- data/lib/video_converter/live_segmenter.rb +1 -1
- data/lib/video_converter/mp4frag.rb +1 -1
- data/lib/video_converter/output.rb +7 -2
- data/lib/video_converter/version.rb +1 -1
- data/lib/video_converter.rb +1 -0
- metadata +20 -37
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 08dc6b011c3952fc94d97cd299f7dedba2c606a5
|
4
|
+
data.tar.gz: 80176473b0719e22ee5794d734a24d717238c0c7
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 8f4d852ba0ced03b88a4f950280817435d8a2a8cd48161cf7526d7014464abeafb6042020995cdb3fad632134d26a705615805d7e13f3cecb024898b1a39b9a7
|
7
|
+
data.tar.gz: 735e997c302281d1e15333d48baf0a815126bf9afa08f816a92ba8c13be8340e506dc80307e71b2f84e868730a84f9cac1d3f9fbdcabb36dcfe6b22610787405
|
data/lib/video_converter/base.rb
CHANGED
@@ -10,7 +10,7 @@ module VideoConverter
|
|
10
10
|
end
|
11
11
|
|
12
12
|
def run
|
13
|
-
convert && faststart && make_screenshots && segment && clear
|
13
|
+
convert && faststart && make_screenshots && segment && encrypt && clear
|
14
14
|
end
|
15
15
|
|
16
16
|
# XXX inject instead of each would be better
|
@@ -37,16 +37,10 @@ module VideoConverter
|
|
37
37
|
|
38
38
|
def segment
|
39
39
|
success = true
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
LiveSegmenter.run(input, group)
|
45
|
-
else
|
46
|
-
Mp4frag.run(input, group)
|
47
|
-
end
|
48
|
-
end
|
49
|
-
end
|
40
|
+
outputs.select { |output| output.type == 'playlist' }.each do |playlist|
|
41
|
+
paths = playlist.streams.map { |stream| stream[:path] }
|
42
|
+
group = outputs.select { |output| paths.include?(output.filename) }.unshift(playlist)
|
43
|
+
success &&= (playlist.filename.end_with?('m3u8') ? LiveSegmenter : Mp4frag).send(:run, group)
|
50
44
|
end
|
51
45
|
success
|
52
46
|
end
|
@@ -63,6 +57,16 @@ module VideoConverter
|
|
63
57
|
Ffmpeg.mux(inputs, outputs.first)
|
64
58
|
end
|
65
59
|
|
60
|
+
def encrypt(options = {})
|
61
|
+
outputs.each do |output|
|
62
|
+
if output.drm == 'adobe'
|
63
|
+
output.options.merge!(options)
|
64
|
+
F4fpackager.run(output) or return false
|
65
|
+
end
|
66
|
+
end
|
67
|
+
true
|
68
|
+
end
|
69
|
+
|
66
70
|
def clear
|
67
71
|
Command.new("cat #{outputs.first.log} >> #{VideoConverter.log} && rm #{outputs.first.log}").execute
|
68
72
|
outputs.map { |output| output.options[:passlogfile] }.uniq.compact.each { |passlogfile| Command.new("rm #{passlogfile}*").execute }
|
@@ -37,7 +37,7 @@ module VideoConverter
|
|
37
37
|
|
38
38
|
def capture params = {}
|
39
39
|
puts command if params[:verbose] || self.class.verbose
|
40
|
-
`#{command}`.encode
|
40
|
+
`#{command}`.encode('UTF-8', 'binary', :invalid => :replace, :undef => :replace, :replace => '')
|
41
41
|
end
|
42
42
|
|
43
43
|
def to_s
|
@@ -0,0 +1,68 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module VideoConverter
|
4
|
+
class F4fpackager
|
5
|
+
class << self
|
6
|
+
attr_accessor :bin, :command, :help_command, :inspect_index_command
|
7
|
+
end
|
8
|
+
|
9
|
+
self.bin = '/usr/local/bin/f4fpackager'
|
10
|
+
self.command = '%{bin} %{options} 1>>%{log} 2>&1 || exit 1'
|
11
|
+
self.help_command = '%{bin} --help'
|
12
|
+
self.inspect_index_command = '%{bin} --input-file %{input_file} --inspect-index'
|
13
|
+
|
14
|
+
def self.run(output)
|
15
|
+
manifest = nil
|
16
|
+
output.streams.each_with_index do |stream, index|
|
17
|
+
VideoConverter::Command.new(command, prepare_params(output.options.merge({
|
18
|
+
:input_file => File.join(output.work_dir, stream[:path]),
|
19
|
+
:output_path => output.work_dir,
|
20
|
+
:bitrate => stream[:bandwidth],
|
21
|
+
:manifest_file => manifest,
|
22
|
+
:log => output.log
|
23
|
+
}))).execute or return false
|
24
|
+
FileUtils.rm manifest if manifest
|
25
|
+
quality = File.basename(stream[:path], '.*')
|
26
|
+
manifest = File.join(output.work_dir, quality + '.f4m')
|
27
|
+
# extract fragments
|
28
|
+
extract_fragments(output, quality) unless output.no_fragments
|
29
|
+
end
|
30
|
+
FileUtils.mv(manifest, File.join(output.work_dir, output.filename))
|
31
|
+
true
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
def self.allowed_options
|
37
|
+
@allowed_options ||= Command.new(help_command, :bin => bin).capture.scan(/--([\w-]+)/).flatten.uniq
|
38
|
+
end
|
39
|
+
|
40
|
+
def self.prepare_params options
|
41
|
+
{
|
42
|
+
:bin => bin,
|
43
|
+
:input_file => options[:input_file],
|
44
|
+
:options => allowed_options.map do |option|
|
45
|
+
if value = options[option.gsub('-', '_').to_sym]
|
46
|
+
'--' + option + (value == true ? '' : ' ' + value.to_s)
|
47
|
+
end
|
48
|
+
end.compact.join(' '),
|
49
|
+
:log => options[:log]
|
50
|
+
}
|
51
|
+
end
|
52
|
+
|
53
|
+
def self.extract_fragments output, quality
|
54
|
+
f4x = File.join(output.work_dir, "#{quality}Seg1.f4x")
|
55
|
+
f4f = f4x.sub('.f4x', '.f4f')
|
56
|
+
next_fragment_offset = File.size(f4f) + 1
|
57
|
+
Command.new(inspect_index_command, prepare_params(:input_file => File.join(output.work_dir, "#{quality}Seg1.f4x"))).capture
|
58
|
+
.scan(/time = (\d+), segment = (\d+), fragment = (\d+), afra-offset = (\d+), offset-from-afra = (\d+)/).reverse
|
59
|
+
.each do |fragment|
|
60
|
+
offset = fragment[3].to_i + fragment[4].to_i
|
61
|
+
File.open(File.join(output.work_dir, "#{quality}Seg#{fragment[1]}-Frag#{fragment[2]}"), 'wb') { |f| f.write IO.read(f4f, next_fragment_offset - offset, offset) }
|
62
|
+
next_fragment_offset = offset
|
63
|
+
end
|
64
|
+
FileUtils.rm f4x
|
65
|
+
FileUtils.rm f4f
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -77,10 +77,7 @@ module VideoConverter
|
|
77
77
|
groups = groups.values
|
78
78
|
|
79
79
|
# qualities of one playlist are one group
|
80
|
-
|
81
|
-
paths = playlist.streams.map { |stream| stream[:path] }
|
82
|
-
groups << outputs.select { |output| paths.include?(output.filename) }.unshift(playlist)
|
83
|
-
end
|
80
|
+
groups += outputs.select { |output| output.type == 'playlist' }.map { |playlist| playlist.output_group(outputs) }
|
84
81
|
|
85
82
|
# other outputs are separate groups
|
86
83
|
(outputs - groups.flatten).each { |output| groups << [output] }
|
@@ -13,7 +13,7 @@ module VideoConverter
|
|
13
13
|
|
14
14
|
self.command = '%{ffmpeg_bin} -i %{ffmpeg_output} -c:v copy -c:a copy -f mpegts pipe:1 2>>/dev/null | %{bin} %{keyframe_interval_in_seconds} %{chunks_dir} %{chunk_prefix} %{encoding_profile} 1>>%{log} 2>&1'
|
15
15
|
|
16
|
-
def self.run(
|
16
|
+
def self.run(outputs)
|
17
17
|
success = true
|
18
18
|
threads = []
|
19
19
|
p = Proc.new do |output|
|
@@ -8,7 +8,7 @@ module VideoConverter
|
|
8
8
|
self.bin = '/usr/local/bin/mp4frag'
|
9
9
|
self.command = '%{bin} %{inputs} --manifest %{manifest} --index 1>>%{log} 2>&1 || exit 1'
|
10
10
|
|
11
|
-
def self.run(
|
11
|
+
def self.run(outputs)
|
12
12
|
success = true
|
13
13
|
threads = []
|
14
14
|
command = Command.new(self.command, prepare_params(outputs))
|
@@ -9,7 +9,7 @@ module VideoConverter
|
|
9
9
|
self.log = 'converter.log'
|
10
10
|
self.keyframe_interval_in_seconds = 4
|
11
11
|
|
12
|
-
attr_accessor :chunks_dir, :faststart, :ffmpeg_output, :filename, :group, :height, :log, :one_pass, :options, :path, :rotate, :streams, :thumbnails, :type, :uid, :width, :work_dir
|
12
|
+
attr_accessor :chunks_dir, :drm, :faststart, :ffmpeg_output, :filename, :group, :height, :log, :no_fragments, :one_pass, :options, :path, :rotate, :streams, :thumbnails, :type, :uid, :width, :work_dir
|
13
13
|
|
14
14
|
def initialize params = {}
|
15
15
|
self.work_dir = File.join(self.class.work_dir, params[:uid])
|
@@ -33,11 +33,16 @@ module VideoConverter
|
|
33
33
|
self.ffmpeg_output = File.join(work_dir, filename)
|
34
34
|
end
|
35
35
|
raise ArgumentError.new('Invalid type') unless %w(default segmented playlist).include?(type)
|
36
|
-
[:path, :streams, :width, :height, :one_pass, :rotate, :faststart, :thumbnails, :group].each { |attr| self.send("#{attr}=", params[attr]) }
|
36
|
+
[:path, :streams, :width, :height, :one_pass, :rotate, :faststart, :thumbnails, :group, :drm, :no_fragments].each { |attr| self.send("#{attr}=", params[attr]) }
|
37
37
|
[:video_bitrate, :audio_bitrate].each { |bitrate| params[bitrate] = "#{params[bitrate]}k" if params[bitrate].is_a?(Numeric) }
|
38
38
|
|
39
39
|
# options will be substituted to convertation commands
|
40
40
|
self.options = params
|
41
41
|
end
|
42
|
+
|
43
|
+
def output_group(outputs)
|
44
|
+
paths = streams.map { |stream| stream[:path] }
|
45
|
+
outputs.select { |output| paths.include?(output.filename) }.unshift(self)
|
46
|
+
end
|
42
47
|
end
|
43
48
|
end
|
data/lib/video_converter.rb
CHANGED
@@ -4,6 +4,7 @@ require "shellwords"
|
|
4
4
|
require "video_converter/array"
|
5
5
|
require "video_converter/base"
|
6
6
|
require "video_converter/command"
|
7
|
+
require "video_converter/f4fpackager"
|
7
8
|
require "video_converter/faststart"
|
8
9
|
require "video_converter/ffmpeg"
|
9
10
|
require "video_converter/hash"
|
metadata
CHANGED
@@ -1,94 +1,83 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: video_converter
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
5
|
-
prerelease:
|
4
|
+
version: 0.7.0
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- novikov
|
9
8
|
autorequire:
|
10
9
|
bindir: bin
|
11
10
|
cert_chain: []
|
12
|
-
date: 2014-08-
|
11
|
+
date: 2014-08-14 00:00:00.000000000 Z
|
13
12
|
dependencies:
|
14
13
|
- !ruby/object:Gem::Dependency
|
15
14
|
name: video_screenshoter
|
16
15
|
requirement: !ruby/object:Gem::Requirement
|
17
|
-
none: false
|
18
16
|
requirements:
|
19
|
-
- - ~>
|
17
|
+
- - "~>"
|
20
18
|
- !ruby/object:Gem::Version
|
21
19
|
version: 0.2.2
|
22
20
|
type: :runtime
|
23
21
|
prerelease: false
|
24
22
|
version_requirements: !ruby/object:Gem::Requirement
|
25
|
-
none: false
|
26
23
|
requirements:
|
27
|
-
- - ~>
|
24
|
+
- - "~>"
|
28
25
|
- !ruby/object:Gem::Version
|
29
26
|
version: 0.2.2
|
30
27
|
- !ruby/object:Gem::Dependency
|
31
28
|
name: bundler
|
32
29
|
requirement: !ruby/object:Gem::Requirement
|
33
|
-
none: false
|
34
30
|
requirements:
|
35
|
-
- - ~>
|
31
|
+
- - "~>"
|
36
32
|
- !ruby/object:Gem::Version
|
37
33
|
version: '1.3'
|
38
34
|
type: :development
|
39
35
|
prerelease: false
|
40
36
|
version_requirements: !ruby/object:Gem::Requirement
|
41
|
-
none: false
|
42
37
|
requirements:
|
43
|
-
- - ~>
|
38
|
+
- - "~>"
|
44
39
|
- !ruby/object:Gem::Version
|
45
40
|
version: '1.3'
|
46
41
|
- !ruby/object:Gem::Dependency
|
47
42
|
name: rake
|
48
43
|
requirement: !ruby/object:Gem::Requirement
|
49
|
-
none: false
|
50
44
|
requirements:
|
51
|
-
- -
|
45
|
+
- - ">="
|
52
46
|
- !ruby/object:Gem::Version
|
53
47
|
version: '0'
|
54
48
|
type: :development
|
55
49
|
prerelease: false
|
56
50
|
version_requirements: !ruby/object:Gem::Requirement
|
57
|
-
none: false
|
58
51
|
requirements:
|
59
|
-
- -
|
52
|
+
- - ">="
|
60
53
|
- !ruby/object:Gem::Version
|
61
54
|
version: '0'
|
62
55
|
- !ruby/object:Gem::Dependency
|
63
56
|
name: test-unit
|
64
57
|
requirement: !ruby/object:Gem::Requirement
|
65
|
-
none: false
|
66
58
|
requirements:
|
67
|
-
- -
|
59
|
+
- - ">="
|
68
60
|
- !ruby/object:Gem::Version
|
69
61
|
version: '0'
|
70
62
|
type: :development
|
71
63
|
prerelease: false
|
72
64
|
version_requirements: !ruby/object:Gem::Requirement
|
73
|
-
none: false
|
74
65
|
requirements:
|
75
|
-
- -
|
66
|
+
- - ">="
|
76
67
|
- !ruby/object:Gem::Version
|
77
68
|
version: '0'
|
78
69
|
- !ruby/object:Gem::Dependency
|
79
70
|
name: shoulda-context
|
80
71
|
requirement: !ruby/object:Gem::Requirement
|
81
|
-
none: false
|
82
72
|
requirements:
|
83
|
-
- -
|
73
|
+
- - ">="
|
84
74
|
- !ruby/object:Gem::Version
|
85
75
|
version: '0'
|
86
76
|
type: :development
|
87
77
|
prerelease: false
|
88
78
|
version_requirements: !ruby/object:Gem::Requirement
|
89
|
-
none: false
|
90
79
|
requirements:
|
91
|
-
- -
|
80
|
+
- - ">="
|
92
81
|
- !ruby/object:Gem::Version
|
93
82
|
version: '0'
|
94
83
|
description: This gem allows you to convert video files using ffmpeg, mencoder and
|
@@ -99,8 +88,8 @@ executables: []
|
|
99
88
|
extensions: []
|
100
89
|
extra_rdoc_files: []
|
101
90
|
files:
|
102
|
-
- .Rakefile.swp
|
103
|
-
- .gitignore
|
91
|
+
- ".Rakefile.swp"
|
92
|
+
- ".gitignore"
|
104
93
|
- Gemfile
|
105
94
|
- LICENSE.txt
|
106
95
|
- README.md
|
@@ -109,6 +98,7 @@ files:
|
|
109
98
|
- lib/video_converter/array.rb
|
110
99
|
- lib/video_converter/base.rb
|
111
100
|
- lib/video_converter/command.rb
|
101
|
+
- lib/video_converter/f4fpackager.rb
|
112
102
|
- lib/video_converter/faststart.rb
|
113
103
|
- lib/video_converter/ffmpeg.rb
|
114
104
|
- lib/video_converter/hash.rb
|
@@ -128,35 +118,28 @@ files:
|
|
128
118
|
homepage: ''
|
129
119
|
licenses:
|
130
120
|
- MIT
|
121
|
+
metadata: {}
|
131
122
|
post_install_message:
|
132
123
|
rdoc_options: []
|
133
124
|
require_paths:
|
134
125
|
- lib
|
135
126
|
required_ruby_version: !ruby/object:Gem::Requirement
|
136
|
-
none: false
|
137
127
|
requirements:
|
138
|
-
- -
|
128
|
+
- - ">="
|
139
129
|
- !ruby/object:Gem::Version
|
140
130
|
version: '0'
|
141
|
-
segments:
|
142
|
-
- 0
|
143
|
-
hash: 1699462479250732562
|
144
131
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
145
|
-
none: false
|
146
132
|
requirements:
|
147
|
-
- -
|
133
|
+
- - ">="
|
148
134
|
- !ruby/object:Gem::Version
|
149
135
|
version: '0'
|
150
|
-
segments:
|
151
|
-
- 0
|
152
|
-
hash: 1699462479250732562
|
153
136
|
requirements:
|
154
137
|
- ffmpeg, version 1.2 or greated configured with libx264 and libfaac
|
155
138
|
- live_segmenter to convert to hls
|
156
139
|
rubyforge_project:
|
157
|
-
rubygems_version:
|
140
|
+
rubygems_version: 2.2.2
|
158
141
|
signing_key:
|
159
|
-
specification_version:
|
142
|
+
specification_version: 4
|
160
143
|
summary: Ffmpeg, mencoder based converter to mp4, m3u8
|
161
144
|
test_files:
|
162
145
|
- test/fixtures/chunk0.ts
|