video_converter 0.6.14 → 0.7.0

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: 08dc6b011c3952fc94d97cd299f7dedba2c606a5
4
+ data.tar.gz: 80176473b0719e22ee5794d734a24d717238c0c7
5
+ SHA512:
6
+ metadata.gz: 8f4d852ba0ced03b88a4f950280817435d8a2a8cd48161cf7526d7014464abeafb6042020995cdb3fad632134d26a705615805d7e13f3cecb024898b1a39b9a7
7
+ data.tar.gz: 735e997c302281d1e15333d48baf0a815126bf9afa08f816a92ba8c13be8340e506dc80307e71b2f84e868730a84f9cac1d3f9fbdcabb36dcfe6b22610787405
@@ -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
- inputs.each do |input|
41
- input.output_groups(input.select_outputs(outputs)).each do |group|
42
- if playlist = group.detect { |output| output.type == 'playlist' }
43
- success &&= if File.extname(playlist.filename) == '.m3u8'
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!('UTF-8', 'UTF-8', :invalid => :replace)
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
- (outputs - groups.flatten).select { |output| output.type == 'playlist' }.each do |playlist|
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(input, outputs)
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(input, outputs)
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
@@ -1,3 +1,3 @@
1
1
  module VideoConverter
2
- VERSION = "0.6.14"
2
+ VERSION = "0.7.0"
3
3
  end
@@ -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.6.14
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-07 00:00:00.000000000 Z
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: 1.8.25
140
+ rubygems_version: 2.2.2
158
141
  signing_key:
159
- specification_version: 3
142
+ specification_version: 4
160
143
  summary: Ffmpeg, mencoder based converter to mp4, m3u8
161
144
  test_files:
162
145
  - test/fixtures/chunk0.ts