video_converter 0.1.0 → 0.1.1
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.
- data/lib/video_converter/ffmpeg.rb +1 -49
- data/lib/video_converter/input.rb +82 -0
- data/lib/video_converter/version.rb +1 -1
- data/lib/video_converter.rb +1 -4
- data/test/input_test.rb +73 -0
- metadata +6 -5
- data/test/ffmpeg_test.rb +0 -37
@@ -3,7 +3,7 @@
|
|
3
3
|
module VideoConverter
|
4
4
|
class Ffmpeg
|
5
5
|
class << self
|
6
|
-
attr_accessor :bin, :one_pass, :one_pass_command, :first_pass_command, :second_pass_command
|
6
|
+
attr_accessor :bin, :one_pass, :one_pass_command, :first_pass_command, :second_pass_command
|
7
7
|
end
|
8
8
|
|
9
9
|
self.bin = '/usr/local/bin/ffmpeg'
|
@@ -16,8 +16,6 @@ module VideoConverter
|
|
16
16
|
|
17
17
|
self.second_pass_command = "%{bin} -i %{input} -y -aspect %{aspect} -acodec copy -vcodec libx264 -g 100 -keyint_min 50 -pass 2 -passlogfile %{input}.log -b:v %{bitrate}k -bt %{bitrate}k -threads %{threads} -f mp4 %{file} 1>%{log} 2>&1 || exit 1"
|
18
18
|
|
19
|
-
self.metadata_command = "%{bin} -i %{input} 2>&1"
|
20
|
-
|
21
19
|
attr_accessor :input, :profile, :one_pass, :paral, :log
|
22
20
|
|
23
21
|
def initialize params
|
@@ -51,56 +49,10 @@ module VideoConverter
|
|
51
49
|
res
|
52
50
|
end
|
53
51
|
|
54
|
-
def metadata
|
55
|
-
metadata = {}
|
56
|
-
s = `#{Command.new self.class.metadata_command, common_params}`
|
57
|
-
if (m = s.match(/Stream.*?Audio:\s*(\w+).*?(\d+)\s*Hz.*?(\d+)\s*kb\/s$/).to_a).any?
|
58
|
-
metadata[:audio_codec] = m[1]
|
59
|
-
metadata[:audio_sample_rate] = m[2].to_i
|
60
|
-
metadata[:audio_bitrate_in_kbps] = m[3].to_i
|
61
|
-
end
|
62
|
-
if (m = s.scan(/Stream #\d+:\d+/)).any?
|
63
|
-
metadata[:channels] = m.count
|
64
|
-
end
|
65
|
-
if (m = s.match(/Duration:\s+(\d+):(\d+):([\d.]+).*?bitrate:\s*(\d+)\s*kb\/s/).to_a).any?
|
66
|
-
metadata[:duration_in_ms] = ((m[1].to_i * 3600 + m[2].to_i * 60 + m[3].to_f) * 1000).to_i
|
67
|
-
metadata[:total_bitrate_in_kbps] = m[4].to_i
|
68
|
-
end
|
69
|
-
if (m = s.match(/Stream.*?Video:\s(\S+).*?,\s*((\d+)x(\d+)).*?(\d+)\s*kb\/s.*?([\d.]+)\s*fps/).to_a).any?
|
70
|
-
metadata[:video_codec] = m[1]
|
71
|
-
metadata[:width] = m[3].to_i
|
72
|
-
metadata[:height] = m[4].to_i
|
73
|
-
metadata[:video_bitrate_in_kbps] = m[5].to_i
|
74
|
-
metadata[:frame_rate] = m[6].to_f
|
75
|
-
end
|
76
|
-
if metadata.any?
|
77
|
-
if is_url?
|
78
|
-
url = URI.parse(input)
|
79
|
-
Net::HTTP.start(url.host) do |http|
|
80
|
-
response = http.request_head url.path
|
81
|
-
metadata[:file_size_in_bytes] = response['content-length'].to_i
|
82
|
-
puts response['content-type']
|
83
|
-
end
|
84
|
-
elsif is_local?
|
85
|
-
metadata[:file_size_in_bytes] = File.size(input)
|
86
|
-
end
|
87
|
-
metadata[:format] = File.extname(input).sub('.', '')
|
88
|
-
end
|
89
|
-
metadata
|
90
|
-
end
|
91
|
-
|
92
52
|
private
|
93
53
|
|
94
54
|
def common_params
|
95
55
|
{ :bin => self.class.bin, :input => input, :log => log }
|
96
56
|
end
|
97
|
-
|
98
|
-
def is_url?
|
99
|
-
!!input.match(/^http:\/\//)
|
100
|
-
end
|
101
|
-
|
102
|
-
def is_local?
|
103
|
-
File.file?(input)
|
104
|
-
end
|
105
57
|
end
|
106
58
|
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module VideoConverter
|
4
|
+
class Input
|
5
|
+
class << self
|
6
|
+
attr_accessor :metadata_command
|
7
|
+
end
|
8
|
+
|
9
|
+
self.metadata_command = "%{bin} -i %{input} 2>&1"
|
10
|
+
|
11
|
+
attr_accessor :input
|
12
|
+
|
13
|
+
def initialize input
|
14
|
+
self.input = input
|
15
|
+
end
|
16
|
+
|
17
|
+
def exists?
|
18
|
+
if is_http?
|
19
|
+
url = URI.parse(input)
|
20
|
+
Net::HTTP.start(url.host) do |http|
|
21
|
+
response = http.request_head url.path
|
22
|
+
Net::HTTPSuccess === response && response['content-type'].include?('video')
|
23
|
+
end
|
24
|
+
elsif is_local?
|
25
|
+
File.file? input
|
26
|
+
else
|
27
|
+
false
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def metadata
|
32
|
+
metadata = {}
|
33
|
+
s = `#{Command.new self.class.metadata_command, common_params}`
|
34
|
+
if (m = s.match(/Stream.*?Audio:\s*(\w+).*?(\d+)\s*Hz.*?(\d+)\s*kb\/s$/).to_a).any?
|
35
|
+
metadata[:audio_codec] = m[1]
|
36
|
+
metadata[:audio_sample_rate] = m[2].to_i
|
37
|
+
metadata[:audio_bitrate_in_kbps] = m[3].to_i
|
38
|
+
end
|
39
|
+
if (m = s.scan(/Stream #\d+:\d+/)).any?
|
40
|
+
metadata[:channels] = m.count
|
41
|
+
end
|
42
|
+
if (m = s.match(/Duration:\s+(\d+):(\d+):([\d.]+).*?bitrate:\s*(\d+)\s*kb\/s/).to_a).any?
|
43
|
+
metadata[:duration_in_ms] = ((m[1].to_i * 3600 + m[2].to_i * 60 + m[3].to_f) * 1000).to_i
|
44
|
+
metadata[:total_bitrate_in_kbps] = m[4].to_i
|
45
|
+
end
|
46
|
+
if (m = s.match(/Stream.*?Video:\s(\S+).*?,\s*((\d+)x(\d+)).*?(\d+)\s*kb\/s.*?([\d.]+)\s*fps/).to_a).any?
|
47
|
+
metadata[:video_codec] = m[1]
|
48
|
+
metadata[:width] = m[3].to_i
|
49
|
+
metadata[:height] = m[4].to_i
|
50
|
+
metadata[:video_bitrate_in_kbps] = m[5].to_i
|
51
|
+
metadata[:frame_rate] = m[6].to_f
|
52
|
+
end
|
53
|
+
if metadata.any?
|
54
|
+
if is_http?
|
55
|
+
url = URI.parse(input)
|
56
|
+
Net::HTTP.start(url.host) do |http|
|
57
|
+
response = http.request_head url.path
|
58
|
+
metadata[:file_size_in_bytes] = response['content-length'].to_i
|
59
|
+
end
|
60
|
+
elsif is_local?
|
61
|
+
metadata[:file_size_in_bytes] = File.size(input)
|
62
|
+
end
|
63
|
+
metadata[:format] = File.extname(input).sub('.', '')
|
64
|
+
end
|
65
|
+
metadata
|
66
|
+
end
|
67
|
+
|
68
|
+
private
|
69
|
+
|
70
|
+
def is_http?
|
71
|
+
!!input.match(/^http:\/\//)
|
72
|
+
end
|
73
|
+
|
74
|
+
def is_local?
|
75
|
+
File.file?(input)
|
76
|
+
end
|
77
|
+
|
78
|
+
def common_params
|
79
|
+
{ :bin => VideoConverter::Ffmpeg.bin, :input => input }
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
data/lib/video_converter.rb
CHANGED
@@ -5,6 +5,7 @@ require "video_converter/command"
|
|
5
5
|
require "video_converter/process"
|
6
6
|
require "video_converter/ffmpeg"
|
7
7
|
require "video_converter/live_segmenter"
|
8
|
+
require "video_converter/input"
|
8
9
|
require "fileutils"
|
9
10
|
require "net/http"
|
10
11
|
|
@@ -24,8 +25,4 @@ module VideoConverter
|
|
24
25
|
def self.find id
|
25
26
|
VideoConverter::Process.new id
|
26
27
|
end
|
27
|
-
|
28
|
-
def self.metadata input
|
29
|
-
VideoConverter::Ffmpeg.new(:input => input).metadata
|
30
|
-
end
|
31
28
|
end
|
data/test/input_test.rb
ADDED
@@ -0,0 +1,73 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class InputTest < Test::Unit::TestCase
|
4
|
+
setup do
|
5
|
+
@test_url = 'http://techslides.com/demos/sample-videos/small.mp4'
|
6
|
+
end
|
7
|
+
|
8
|
+
context 'exists' do
|
9
|
+
context 'when it is local' do
|
10
|
+
context 'and exists' do
|
11
|
+
should 'return true' do
|
12
|
+
assert VideoConverter::Input.new('test/fixtures/test.mp4').exists?
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
context 'and does not exist or is not file' do
|
17
|
+
should 'return false' do
|
18
|
+
assert !VideoConverter::Input.new('test/fixtures/not_existed_file').exists?
|
19
|
+
assert !VideoConverter::Input.new('test/fixtures').exists?
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
context 'when it is http' do
|
25
|
+
context 'and exists' do
|
26
|
+
should 'return true' do
|
27
|
+
assert VideoConverter::Input.new(@test_url)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
context 'when does not exist or is not file' do
|
32
|
+
should 'return false' do
|
33
|
+
assert !VideoConverter::Input.new(@test_url + 'any').exists?
|
34
|
+
assert !VideoConverter::Input.new(URI.parse(@test_url).host).exists?
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
context 'metadata' do
|
41
|
+
context 'when input does not exist' do
|
42
|
+
should 'be empty' do
|
43
|
+
assert VideoConverter::Input.new('test/fixtures/not_existed_file').metadata.empty?
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
context 'when input is dir' do
|
48
|
+
should 'be empty' do
|
49
|
+
assert VideoConverter::Input.new('tmp/fixtures').metadata.empty?
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
context 'when input is not video file' do
|
54
|
+
should 'be empty' do
|
55
|
+
assert VideoConverter::Input.new(__FILE__).metadata.empty?
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
context 'when input is video file' do
|
60
|
+
should 'not be empty' do
|
61
|
+
h = {:audio_bitrate_in_kbps=>97, :audio_codec=>"aac", :audio_sample_rate=>44100, :channels=>2, :duration_in_ms=>4019, :total_bitrate_in_kbps=>1123, :frame_rate=>29.97, :height=>360, :video_bitrate_in_kbps=>1020, :video_codec=>"h264", :width=>640, :file_size_in_bytes=>564356, :format=>"mp4"}
|
62
|
+
assert_equal h, VideoConverter::Input.new('test/fixtures/test.mp4').metadata
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
context 'when input is url' do
|
67
|
+
should 'not be empty' do
|
68
|
+
h = {:audio_codec=>"aac", :audio_sample_rate=>48000, :audio_bitrate_in_kbps=>83, :channels=>2, :duration_in_ms=>5570, :total_bitrate_in_kbps=>551, :video_codec=>"h264", :width=>560, :height=>320, :video_bitrate_in_kbps=>465, :frame_rate=>30.0, :file_size_in_bytes=>383631, :format=>"mp4"}
|
69
|
+
assert_equal h, VideoConverter::Input.new(@test_url).metadata
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: video_converter
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.1
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -93,14 +93,15 @@ files:
|
|
93
93
|
- lib/video_converter/base.rb
|
94
94
|
- lib/video_converter/command.rb
|
95
95
|
- lib/video_converter/ffmpeg.rb
|
96
|
+
- lib/video_converter/input.rb
|
96
97
|
- lib/video_converter/live_segmenter.rb
|
97
98
|
- lib/video_converter/process.rb
|
98
99
|
- lib/video_converter/profile.rb
|
99
100
|
- lib/video_converter/version.rb
|
100
|
-
- test/ffmpeg_test.rb
|
101
101
|
- test/fixtures/test.mp4
|
102
102
|
- test/fixtures/test.mp4.log-0.log
|
103
103
|
- test/fixtures/test.mp4.log-0.log.mbtree
|
104
|
+
- test/input_test.rb
|
104
105
|
- test/test_helper.rb
|
105
106
|
- test/video_converter_test.rb
|
106
107
|
- video_converter.gemspec
|
@@ -119,7 +120,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
119
120
|
version: '0'
|
120
121
|
segments:
|
121
122
|
- 0
|
122
|
-
hash: -
|
123
|
+
hash: -530549277502155145
|
123
124
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
124
125
|
none: false
|
125
126
|
requirements:
|
@@ -128,7 +129,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
128
129
|
version: '0'
|
129
130
|
segments:
|
130
131
|
- 0
|
131
|
-
hash: -
|
132
|
+
hash: -530549277502155145
|
132
133
|
requirements:
|
133
134
|
- ffmpeg, version 1.2 or greated configured with libx264 and libfaac
|
134
135
|
- live_segmenter to convert to hls
|
@@ -138,9 +139,9 @@ signing_key:
|
|
138
139
|
specification_version: 3
|
139
140
|
summary: Ffmpeg, mencoder based converter to mp4, m3u8
|
140
141
|
test_files:
|
141
|
-
- test/ffmpeg_test.rb
|
142
142
|
- test/fixtures/test.mp4
|
143
143
|
- test/fixtures/test.mp4.log-0.log
|
144
144
|
- test/fixtures/test.mp4.log-0.log.mbtree
|
145
|
+
- test/input_test.rb
|
145
146
|
- test/test_helper.rb
|
146
147
|
- test/video_converter_test.rb
|
data/test/ffmpeg_test.rb
DELETED
@@ -1,37 +0,0 @@
|
|
1
|
-
require 'test_helper'
|
2
|
-
|
3
|
-
class FfmpegTest < Test::Unit::TestCase
|
4
|
-
context 'metadata' do
|
5
|
-
context 'when input does not exist' do
|
6
|
-
should 'be empty' do
|
7
|
-
assert VideoConverter::Ffmpeg.new(:input => 'tmp/fixtures/not_existed_file').metadata.empty?
|
8
|
-
end
|
9
|
-
end
|
10
|
-
|
11
|
-
context 'when input is dir' do
|
12
|
-
should 'be empty' do
|
13
|
-
assert VideoConverter::Ffmpeg.new(:input => 'tmp/fixtures').metadata.empty?
|
14
|
-
end
|
15
|
-
end
|
16
|
-
|
17
|
-
context 'when input is not video file' do
|
18
|
-
should 'be empty' do
|
19
|
-
assert VideoConverter::Ffmpeg.new(:input => __FILE__).metadata.empty?
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
context 'when input is video file' do
|
24
|
-
should 'not be empty' do
|
25
|
-
h = {:audio_bitrate_in_kbps=>97, :audio_codec=>"aac", :audio_sample_rate=>44100, :channels=>2, :duration_in_ms=>4019, :total_bitrate_in_kbps=>1123, :frame_rate=>29.97, :height=>360, :video_bitrate_in_kbps=>1020, :video_codec=>"h264", :width=>640, :file_size_in_bytes=>564356, :format=>"mp4"}
|
26
|
-
assert_equal h, VideoConverter::Ffmpeg.new(:input => 'test/fixtures/test.mp4').metadata
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
context 'when input is url' do
|
31
|
-
should 'not be empty' do
|
32
|
-
h = {:audio_codec=>"aac", :audio_sample_rate=>48000, :audio_bitrate_in_kbps=>83, :channels=>2, :duration_in_ms=>5570, :total_bitrate_in_kbps=>551, :video_codec=>"h264", :width=>560, :height=>320, :video_bitrate_in_kbps=>465, :frame_rate=>30.0, :file_size_in_bytes=>383631, :format=>"mp4"}
|
33
|
-
assert_equal h, VideoConverter::Ffmpeg.new(:input => 'http://techslides.com/demos/sample-videos/small.mp4').metadata
|
34
|
-
end
|
35
|
-
end
|
36
|
-
end
|
37
|
-
end
|