video_converter 0.1.0 → 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|