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 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