mkv2m4v 0.0.1 → 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/.gitignore +0 -1
- data/README.md +35 -6
- data/Rakefile +9 -0
- data/doc/notes.md +26 -0
- data/lib/mkv2m4v/file.rb +80 -0
- data/lib/mkv2m4v/track.rb +86 -0
- data/lib/mkv2m4v/track_ranker.rb +64 -0
- data/lib/mkv2m4v/transcoder.rb +141 -0
- data/lib/mkv2m4v/version.rb +1 -1
- data/lib/mkv2m4v.rb +10 -44
- data/mkv2m4v.gemspec +7 -2
- data/test/test_helper.rb +2 -0
- metadata +80 -4
- data/lib/mkv2m4v/mediainfo.rb +0 -13
data/.gitignore
CHANGED
data/README.md
CHANGED
@@ -1,6 +1,3 @@
|
|
1
|
-
**This gem is a work in progress.** Do not expect any supported functionality
|
2
|
-
until v0.1.0.
|
3
|
-
|
4
1
|
# mkv2m4v
|
5
2
|
|
6
3
|
Converts audio and video tracks from a MKV (Matroska Media) container into a
|
@@ -15,12 +12,44 @@ It attempts to pass through as many codecs as possible.
|
|
15
12
|
|
16
13
|
## Installation
|
17
14
|
|
18
|
-
|
19
|
-
|
15
|
+
mkv2m4v is dependent upon `mediainfo`, `mkvextract`, `ffmpeg`, and `MP4Box`.
|
16
|
+
|
17
|
+
```bash
|
18
|
+
$ brew install mediainfo
|
19
|
+
$ brew install gpac
|
20
|
+
$ brew install mkvtoolnix
|
21
|
+
$ gem install mkv2m4v
|
22
|
+
```
|
23
|
+
|
24
|
+
_Note: `gpac` includes `MP4Box` and is dependent on `ffmpeg`, so `ffmpeg`
|
25
|
+
should install automatically. If not, you should manually install `ffmpeg`:_
|
26
|
+
|
27
|
+
```bash
|
28
|
+
# ffmpeg should already be installed, but just in case:
|
29
|
+
$ brew install ffmpeg --with-tools
|
30
|
+
```
|
20
31
|
|
21
32
|
## Usage
|
22
33
|
|
23
|
-
|
34
|
+
```bash
|
35
|
+
$ mkv2m4v some-video.mkv
|
36
|
+
```
|
37
|
+
|
38
|
+
## Background
|
39
|
+
|
40
|
+
I got fed up with the reliability of the conversion tools out there for
|
41
|
+
converting MKV video containers to Apple TV compatible videos. Many of the
|
42
|
+
existing tools appear to have potential on the surface, but they fail under
|
43
|
+
certain scenarios.
|
44
|
+
|
45
|
+
[Handbrake](http://handbrake.fr/) is still the most realiable existing tool
|
46
|
+
out there, but it re-encodes h.264 video tracks, which is not ideal and very
|
47
|
+
slow.
|
48
|
+
|
49
|
+
The goal is to get a better, more automated tool to accomplish the task of
|
50
|
+
generating Apple TV compatible videos. Nothing more. It should generate an M4V
|
51
|
+
media file with the best possible quality given the original source and the
|
52
|
+
defaults should require no additional human interaction.
|
24
53
|
|
25
54
|
## Contributing
|
26
55
|
|
data/Rakefile
CHANGED
data/doc/notes.md
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
Extracting tracks from an mkv (assuming correct track numbers):
|
2
|
+
|
3
|
+
$ mediainfo example.mkv # Inspect track IDs
|
4
|
+
$ mkvextract tracks example.mkv 1:example.h264 2:example.dts
|
5
|
+
|
6
|
+
Converting dts to ac3:
|
7
|
+
|
8
|
+
$ ffmpeg -i example.dts -acodec ac3 -ac 6 -ab 640k example-6ch.ac3
|
9
|
+
|
10
|
+
Converting dts to aac:
|
11
|
+
|
12
|
+
$ ffmpeg -i example.dts -acodec libfaac -ac 2 -ab 160k example-2ch.aac
|
13
|
+
|
14
|
+
Converting ac3 to aac:
|
15
|
+
|
16
|
+
$ ffmpeg -i example.ac3 -acodec libfaac -ac 2 -ab 160k example-2ch.aac
|
17
|
+
|
18
|
+
Remux the tracks into an M4V container. For Apple TV surround sound support,
|
19
|
+
the audio tracks must be in the same group with all but the first AAC track
|
20
|
+
disabled. [[source](http://forum.doom9.org/archive/index.php/t-160302.html)]
|
21
|
+
|
22
|
+
$ MP4Box \
|
23
|
+
-add example.h264:lang=en:name="AVC Video" \
|
24
|
+
-add example-2ch.aac:lang=en:group=1:delay=84:name="Stereo" \
|
25
|
+
-add example-6ch.ac3:lang=en:group=1:delay=84:disable:name="AC3" \
|
26
|
+
-new example_testing.m4v
|
data/lib/mkv2m4v/file.rb
ADDED
@@ -0,0 +1,80 @@
|
|
1
|
+
require "mkv2m4v/track"
|
2
|
+
require "mkv2m4v/track_ranker"
|
3
|
+
require "mkv2m4v/transcoder"
|
4
|
+
require "mediainfo"
|
5
|
+
require "forwardable"
|
6
|
+
require "iso639"
|
7
|
+
require "colorize"
|
8
|
+
|
9
|
+
module Mkv2m4v
|
10
|
+
class File
|
11
|
+
extend Forwardable
|
12
|
+
|
13
|
+
attr_reader :info, :video_tracks, :audio_tracks, :text_tracks
|
14
|
+
attr_reader :ideal_video_track, :ideal_audio_track
|
15
|
+
def_delegator :info, :filename, :name
|
16
|
+
def_delegator :info, :full_filename, :filename
|
17
|
+
|
18
|
+
def initialize(filename, options = {})
|
19
|
+
@info = Mediainfo.new(filename)
|
20
|
+
@options = options
|
21
|
+
@languages = @options[:languages]
|
22
|
+
init_tracks
|
23
|
+
end
|
24
|
+
|
25
|
+
def format
|
26
|
+
info.general.format
|
27
|
+
end
|
28
|
+
|
29
|
+
def print
|
30
|
+
puts "#{format}: #{name}".black.on_yellow
|
31
|
+
video_tracks.filter.each(&:print) if @options[:verbose]
|
32
|
+
audio_tracks.filter.each(&:print) if @options[:verbose]
|
33
|
+
text_tracks.filter.each(&:print) if @options[:verbose]
|
34
|
+
print_ideal_tracks
|
35
|
+
puts
|
36
|
+
end
|
37
|
+
|
38
|
+
def transcode
|
39
|
+
puts "#{format}: #{name}".black.on_yellow
|
40
|
+
Transcoder.new(self, @options).run
|
41
|
+
puts
|
42
|
+
end
|
43
|
+
|
44
|
+
def self.each(filenames, options = {})
|
45
|
+
filenames.each do |filename|
|
46
|
+
if ::File.exists?(filename)
|
47
|
+
yield new(filename, options)
|
48
|
+
else
|
49
|
+
$stderr.puts "#{filename} does not exist."
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
private
|
55
|
+
|
56
|
+
def print_ideal_tracks
|
57
|
+
puts "==> Ideal video track"
|
58
|
+
@ideal_video_track.print
|
59
|
+
puts "==> Ideal audio track"
|
60
|
+
@ideal_audio_track.print
|
61
|
+
end
|
62
|
+
|
63
|
+
def init_tracks
|
64
|
+
@video_tracks = tracks_by_type(:video)
|
65
|
+
@audio_tracks = tracks_by_type(:audio)
|
66
|
+
@text_tracks = tracks_by_type(:text)
|
67
|
+
|
68
|
+
@ideal_video_track = video_tracks.filter.rank.first
|
69
|
+
@ideal_audio_track = audio_tracks.filter.rank.first
|
70
|
+
end
|
71
|
+
|
72
|
+
def tracks_by_type(type)
|
73
|
+
info_tracks = info.send(type)
|
74
|
+
tracks = info_tracks.count.times.map do |i|
|
75
|
+
Mkv2m4v.const_get("#{type.capitalize}Track").new(info_tracks[i])
|
76
|
+
end
|
77
|
+
Mkv2m4v.const_get("#{type.capitalize}Ranker").new(tracks, @options)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,86 @@
|
|
1
|
+
require "forwardable"
|
2
|
+
|
3
|
+
module Mkv2m4v
|
4
|
+
class Track
|
5
|
+
extend Forwardable
|
6
|
+
|
7
|
+
attr_reader :info
|
8
|
+
def_delegator :info, :stream_id, :id
|
9
|
+
def_delegators :info, :format
|
10
|
+
|
11
|
+
def initialize(track_info)
|
12
|
+
@info = track_info
|
13
|
+
end
|
14
|
+
|
15
|
+
def language
|
16
|
+
Iso639[info["language"]]
|
17
|
+
end
|
18
|
+
|
19
|
+
def title
|
20
|
+
info["title"]
|
21
|
+
end
|
22
|
+
|
23
|
+
def format_description
|
24
|
+
"#{format} (#{info.format_info}, #{info.codec_id})"
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
class VideoTrack < Track
|
29
|
+
def_delegators :info, :frame_size, :interlaced?, :fps, :width, :height
|
30
|
+
|
31
|
+
def resolution
|
32
|
+
"#{frame_size}#{interlaced? ? "i" : "p"}"
|
33
|
+
end
|
34
|
+
|
35
|
+
def print
|
36
|
+
puts "Track #{id}: (video)"
|
37
|
+
puts " Format: #{format_description}"
|
38
|
+
puts " Resolution: #{resolution}"
|
39
|
+
puts " FPS: #{fps}"
|
40
|
+
puts " Language: #{language}"
|
41
|
+
puts " Title: #{title}"
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
class AudioTrack < Track
|
46
|
+
def_delegators :info, :bit_rate
|
47
|
+
|
48
|
+
def channel_count
|
49
|
+
info.channels.to_s.chars.first.to_i
|
50
|
+
end
|
51
|
+
|
52
|
+
def bit_rate_kbps
|
53
|
+
info.bit_rate.gsub(/\D/, "").to_i if info.bit_rate
|
54
|
+
end
|
55
|
+
|
56
|
+
def channel_description
|
57
|
+
"#{channel_count} (#{info.channel_positions})"
|
58
|
+
end
|
59
|
+
|
60
|
+
def bit_rate_description
|
61
|
+
"#{bit_rate_kbps}k (#{info.bit_rate_mode})"
|
62
|
+
end
|
63
|
+
|
64
|
+
def print
|
65
|
+
puts "Track #{id}: (audio)"
|
66
|
+
puts " Format: #{format_description}"
|
67
|
+
puts " Channels: #{channel_description}"
|
68
|
+
puts " Bit rate: #{bit_rate_description}"
|
69
|
+
puts " Language: #{language}"
|
70
|
+
puts " Title: #{title}"
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
class TextTrack < Track
|
75
|
+
def format_description
|
76
|
+
"#{format} (#{info.codec_id})"
|
77
|
+
end
|
78
|
+
|
79
|
+
def print
|
80
|
+
puts "Track #{id}: (text)"
|
81
|
+
puts " Format: #{format_description}"
|
82
|
+
puts " Language: #{language}"
|
83
|
+
puts " Title: #{title}"
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
require "forwardable"
|
2
|
+
|
3
|
+
module Mkv2m4v
|
4
|
+
class TrackRanker
|
5
|
+
extend Forwardable
|
6
|
+
|
7
|
+
def_delegators :@tracks, :each, :first
|
8
|
+
|
9
|
+
def initialize(tracks, options = {})
|
10
|
+
@tracks = tracks
|
11
|
+
@options = options
|
12
|
+
end
|
13
|
+
|
14
|
+
def filter
|
15
|
+
filtered_tracks = @tracks.select { |t| language_okay?(t) }
|
16
|
+
self.class.new(filtered_tracks, @options)
|
17
|
+
end
|
18
|
+
|
19
|
+
def rank
|
20
|
+
ranked_tracks = @tracks.sort_by { |t| score(t) }.reverse
|
21
|
+
self.class.new(ranked_tracks, @options)
|
22
|
+
end
|
23
|
+
|
24
|
+
protected
|
25
|
+
|
26
|
+
def language_match?(track)
|
27
|
+
@options.languages.include?(track.language)
|
28
|
+
end
|
29
|
+
|
30
|
+
def language_okay?(track)
|
31
|
+
track.language.nil? ||
|
32
|
+
@options.languages.empty? ||
|
33
|
+
language_match?(track)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
class VideoRanker < TrackRanker
|
38
|
+
def score(track)
|
39
|
+
score = 0
|
40
|
+
score += 8 if track.format == "AVC"
|
41
|
+
score += (track.height || 0)/ 1080.0 * 4.0
|
42
|
+
score += 2 if language_match?(track)
|
43
|
+
score
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
class AudioRanker < TrackRanker
|
48
|
+
def score(track)
|
49
|
+
score = 0
|
50
|
+
score += 4 if ["DTS", "AC-3"].include?(track.format)
|
51
|
+
score += 2 if track.format == "AAC"
|
52
|
+
score += (track.channel_count || 0) / 8.0 * 2.0
|
53
|
+
score += (track.bit_rate_kbps || 0) / 1500.0 * 2.0
|
54
|
+
score += 4 if language_match?(track)
|
55
|
+
score
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
class TextRanker < TrackRanker
|
60
|
+
# scoring not implemented yet
|
61
|
+
# def score(track)
|
62
|
+
# end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,141 @@
|
|
1
|
+
require "fileutils"
|
2
|
+
require "colorize"
|
3
|
+
|
4
|
+
module Mkv2m4v
|
5
|
+
class Transcoder
|
6
|
+
def initialize(file, options = {})
|
7
|
+
@file = file
|
8
|
+
@options = options
|
9
|
+
end
|
10
|
+
|
11
|
+
def run
|
12
|
+
setup
|
13
|
+
extract
|
14
|
+
transcode_avc
|
15
|
+
transcode_aac
|
16
|
+
transcode_ac3
|
17
|
+
remux
|
18
|
+
cleanup
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def setup
|
24
|
+
FileUtils.mkdir_p tmp_dir
|
25
|
+
end
|
26
|
+
|
27
|
+
def extract
|
28
|
+
puts "==> Extracting #{video_id}:video.#{video_ext} #{audio_id}:audio.#{audio_ext} ".magenta
|
29
|
+
system "mkvextract tracks #{@file.filename.inspect} #{video_id}:#{video_file} #{audio_id}:#{audio_file}"
|
30
|
+
end
|
31
|
+
|
32
|
+
def transcode_avc
|
33
|
+
if video_format == "AVC"
|
34
|
+
puts "==> Assuming pass through for h.264 video track".yellow.on_black
|
35
|
+
else
|
36
|
+
puts "==> ERROR: Wrong Video format".white.on_red
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def transcode_aac
|
41
|
+
if audio_format == "AAC"
|
42
|
+
puts "==> Assuming pass through for AAC audio track".yellow.on_black
|
43
|
+
else
|
44
|
+
puts "==> Transcoding #{audio_format} to Stereo AAC audio track".magenta
|
45
|
+
system "ffmpeg -i #{audio_file.inspect} -acodec libfaac -ac 2 -ab 160k #{audio_basename}.aac"
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def transcode_ac3
|
50
|
+
if audio_format == "AC-3"
|
51
|
+
puts "==> Assuming pass through for AC-3 audio track".yellow.on_black
|
52
|
+
elsif audio_format == "AAC"
|
53
|
+
puts "==> Skipping AC-3 surround audio track".yellow.on_black
|
54
|
+
@skip_ac3 = true
|
55
|
+
else
|
56
|
+
puts "==> Transcoding #{audio_format} to Surround AC-3 audio track".magenta
|
57
|
+
system "ffmpeg -i #{audio_file.inspect} -acodec ac3 -ac #{max_audio_channels} -ab #{max_audio_bit_rate}k #{audio_basename}.ac3"
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def remux
|
62
|
+
puts "==> Remuxing everything into an M4V container".magenta
|
63
|
+
command = "MP4Box"
|
64
|
+
command << " -add #{video_basename.inspect}.h264:lang=en:name=\"AVC Video\" "
|
65
|
+
command << " -add #{audio_basename.inspect}.aac:lang=en:group=1:delay=84:name=\"Stereo\" "
|
66
|
+
unless @skip_ac3
|
67
|
+
command << " -add #{audio_basename.inspect}.ac3:lang=en:group=1:delay=84:disable:name=\"AC3\" "
|
68
|
+
end
|
69
|
+
command << " -new #{m4v_file.inspect}"
|
70
|
+
system command
|
71
|
+
end
|
72
|
+
|
73
|
+
def cleanup
|
74
|
+
FileUtils.rm_rf tmp_dir
|
75
|
+
end
|
76
|
+
|
77
|
+
def video_basename
|
78
|
+
::File.join(tmp_dir, "video")
|
79
|
+
end
|
80
|
+
|
81
|
+
def video_file
|
82
|
+
[video_basename, video_ext].join(".")
|
83
|
+
end
|
84
|
+
|
85
|
+
def video_id
|
86
|
+
@file.ideal_video_track.id
|
87
|
+
end
|
88
|
+
|
89
|
+
def video_format
|
90
|
+
@file.ideal_video_track.format
|
91
|
+
end
|
92
|
+
|
93
|
+
def video_ext
|
94
|
+
if video_format == "AVC"
|
95
|
+
"h264"
|
96
|
+
else
|
97
|
+
video_format.gsub(/\W/, "").downcase
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
def audio_basename
|
102
|
+
::File.join(tmp_dir, "audio")
|
103
|
+
end
|
104
|
+
|
105
|
+
def audio_file
|
106
|
+
[audio_basename, audio_ext].join(".")
|
107
|
+
end
|
108
|
+
|
109
|
+
def audio_id
|
110
|
+
@file.ideal_audio_track.id
|
111
|
+
end
|
112
|
+
|
113
|
+
def audio_format
|
114
|
+
@file.ideal_audio_track.format
|
115
|
+
end
|
116
|
+
|
117
|
+
def audio_ext
|
118
|
+
audio_format.gsub(/\W/, "").downcase
|
119
|
+
end
|
120
|
+
|
121
|
+
def max_audio_channels
|
122
|
+
[@file.ideal_audio_track.channel_count, 6].min
|
123
|
+
end
|
124
|
+
|
125
|
+
def max_audio_bit_rate
|
126
|
+
[@file.ideal_audio_track.bit_rate_kbps, 640].min
|
127
|
+
end
|
128
|
+
|
129
|
+
def dir
|
130
|
+
@options[:dir] || ::File.dirname(@file.filename)
|
131
|
+
end
|
132
|
+
|
133
|
+
def tmp_dir
|
134
|
+
::File.join(dir, ::File.basename(@file.name, ".*") + "-tracks")
|
135
|
+
end
|
136
|
+
|
137
|
+
def m4v_file
|
138
|
+
::File.join(dir, ::File.basename(@file.name, ".*") + ".m4v")
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
data/lib/mkv2m4v/version.rb
CHANGED
data/lib/mkv2m4v.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
require "mkv2m4v/version"
|
2
|
-
require "mkv2m4v/
|
2
|
+
require "mkv2m4v/file"
|
3
3
|
require "trollop"
|
4
4
|
|
5
5
|
module Mkv2m4v
|
@@ -10,56 +10,17 @@ module Mkv2m4v
|
|
10
10
|
|
11
11
|
def run
|
12
12
|
if @options[:info]
|
13
|
-
|
13
|
+
each_file(&:print)
|
14
14
|
else
|
15
|
-
|
15
|
+
each_file(&:transcode)
|
16
16
|
end
|
17
17
|
end
|
18
18
|
|
19
19
|
private
|
20
20
|
|
21
|
-
def convert_files
|
22
|
-
$stderr.puts "Converting files is not yet supported. For now, try the --info option."
|
23
|
-
# each_file do |file|
|
24
|
-
# end
|
25
|
-
end
|
26
|
-
|
27
|
-
def print_info
|
28
|
-
each_file do |file|
|
29
|
-
info = Mediainfo.new file
|
30
|
-
puts "#{info.general.format}: #{file}"
|
31
|
-
info.video.count.times do |i|
|
32
|
-
print_video_track(info.video[i])
|
33
|
-
end
|
34
|
-
info.audio.count.times do |i|
|
35
|
-
print_audio_track(info.audio[i])
|
36
|
-
end
|
37
|
-
puts
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
def print_video_track(video)
|
42
|
-
puts "Video Track #{video.stream_id}:"
|
43
|
-
puts " Format: #{video.format} (#{video.format_info}, #{video.codec_id})"
|
44
|
-
puts " Resolution: #{video.frame_size}#{video.interlaced? ? "i" : "p"}"
|
45
|
-
puts " FPS: #{video.fps}"
|
46
|
-
puts " Language: #{video.language}"
|
47
|
-
end
|
48
|
-
|
49
|
-
def print_audio_track(audio)
|
50
|
-
puts "Audio Track #{audio.stream_id}:"
|
51
|
-
puts " Format: #{audio.format} (#{audio.format_info}, #{audio.codec_id})"
|
52
|
-
puts " Channels: #{audio.channel_count} (#{audio.channel_positions})"
|
53
|
-
puts " Language: #{audio.language}"
|
54
|
-
end
|
55
|
-
|
56
21
|
def each_file
|
57
|
-
|
58
|
-
|
59
|
-
yield file
|
60
|
-
else
|
61
|
-
$stderr.puts "#{file} does not exist."
|
62
|
-
end
|
22
|
+
Mkv2m4v::File.each(@filenames, @options) do |file|
|
23
|
+
yield file
|
63
24
|
end
|
64
25
|
end
|
65
26
|
|
@@ -69,7 +30,12 @@ module Mkv2m4v
|
|
69
30
|
version Mkv2m4v::VersionDescription
|
70
31
|
banner [Mkv2m4v::Description, Mkv2m4v::Usage].join("\n")
|
71
32
|
opt :info, "Print media info only"
|
33
|
+
opt :lang, "Preferred languages", :type => :strings, :default => ["English"]
|
34
|
+
opt :dir, "Destination directory", :type => :string
|
35
|
+
opt :verbose, "More output", :type => :boolean
|
72
36
|
end
|
37
|
+
@options[:languages] = @options[:lang].map { |lang| Iso639[lang] }.compact
|
38
|
+
@filenames = ARGV
|
73
39
|
end
|
74
40
|
end
|
75
41
|
end
|
data/mkv2m4v.gemspec
CHANGED
@@ -17,6 +17,11 @@ Gem::Specification.new do |gem|
|
|
17
17
|
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
18
18
|
gem.require_paths = ["lib"]
|
19
19
|
|
20
|
-
gem.add_dependency
|
21
|
-
gem.add_dependency
|
20
|
+
gem.add_dependency "trollop", "~> 2.0"
|
21
|
+
gem.add_dependency "mediainfo", "~> 0.7"
|
22
|
+
gem.add_dependency "iso639", "~> 1.0", ">= 1.0.5"
|
23
|
+
gem.add_dependency "colorize", "~> 0.5"
|
24
|
+
|
25
|
+
gem.add_development_dependency "minitest", "~> 4.3"
|
26
|
+
gem.add_development_dependency "rake", "~> 10.0"
|
22
27
|
end
|
data/test/test_helper.rb
ADDED
metadata
CHANGED
@@ -2,14 +2,14 @@
|
|
2
2
|
name: mkv2m4v
|
3
3
|
version: !ruby/object:Gem::Version
|
4
4
|
prerelease:
|
5
|
-
version: 0.
|
5
|
+
version: 0.1.1
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Ryan McGeary
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-12-
|
12
|
+
date: 2012-12-25 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -43,6 +43,76 @@ dependencies:
|
|
43
43
|
- !ruby/object:Gem::Version
|
44
44
|
version: '0.7'
|
45
45
|
none: false
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
version_requirements: !ruby/object:Gem::Requirement
|
48
|
+
requirements:
|
49
|
+
- - ~>
|
50
|
+
- !ruby/object:Gem::Version
|
51
|
+
version: '1.0'
|
52
|
+
- - ! '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 1.0.5
|
55
|
+
none: false
|
56
|
+
name: iso639
|
57
|
+
type: :runtime
|
58
|
+
prerelease: false
|
59
|
+
requirement: !ruby/object:Gem::Requirement
|
60
|
+
requirements:
|
61
|
+
- - ~>
|
62
|
+
- !ruby/object:Gem::Version
|
63
|
+
version: '1.0'
|
64
|
+
- - ! '>='
|
65
|
+
- !ruby/object:Gem::Version
|
66
|
+
version: 1.0.5
|
67
|
+
none: false
|
68
|
+
- !ruby/object:Gem::Dependency
|
69
|
+
version_requirements: !ruby/object:Gem::Requirement
|
70
|
+
requirements:
|
71
|
+
- - ~>
|
72
|
+
- !ruby/object:Gem::Version
|
73
|
+
version: '0.5'
|
74
|
+
none: false
|
75
|
+
name: colorize
|
76
|
+
type: :runtime
|
77
|
+
prerelease: false
|
78
|
+
requirement: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ~>
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0.5'
|
83
|
+
none: false
|
84
|
+
- !ruby/object:Gem::Dependency
|
85
|
+
version_requirements: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ~>
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '4.3'
|
90
|
+
none: false
|
91
|
+
name: minitest
|
92
|
+
type: :development
|
93
|
+
prerelease: false
|
94
|
+
requirement: !ruby/object:Gem::Requirement
|
95
|
+
requirements:
|
96
|
+
- - ~>
|
97
|
+
- !ruby/object:Gem::Version
|
98
|
+
version: '4.3'
|
99
|
+
none: false
|
100
|
+
- !ruby/object:Gem::Dependency
|
101
|
+
version_requirements: !ruby/object:Gem::Requirement
|
102
|
+
requirements:
|
103
|
+
- - ~>
|
104
|
+
- !ruby/object:Gem::Version
|
105
|
+
version: '10.0'
|
106
|
+
none: false
|
107
|
+
name: rake
|
108
|
+
type: :development
|
109
|
+
prerelease: false
|
110
|
+
requirement: !ruby/object:Gem::Requirement
|
111
|
+
requirements:
|
112
|
+
- - ~>
|
113
|
+
- !ruby/object:Gem::Version
|
114
|
+
version: '10.0'
|
115
|
+
none: false
|
46
116
|
description: ! 'mkv2m4v is a command line utility that converts audio and video tracks
|
47
117
|
from a
|
48
118
|
|
@@ -62,10 +132,15 @@ files:
|
|
62
132
|
- README.md
|
63
133
|
- Rakefile
|
64
134
|
- bin/mkv2m4v
|
135
|
+
- doc/notes.md
|
65
136
|
- lib/mkv2m4v.rb
|
66
|
-
- lib/mkv2m4v/
|
137
|
+
- lib/mkv2m4v/file.rb
|
138
|
+
- lib/mkv2m4v/track.rb
|
139
|
+
- lib/mkv2m4v/track_ranker.rb
|
140
|
+
- lib/mkv2m4v/transcoder.rb
|
67
141
|
- lib/mkv2m4v/version.rb
|
68
142
|
- mkv2m4v.gemspec
|
143
|
+
- test/test_helper.rb
|
69
144
|
homepage: https://github.com/rmm5t/mkv2m4v
|
70
145
|
licenses: []
|
71
146
|
post_install_message:
|
@@ -90,4 +165,5 @@ rubygems_version: 1.8.23
|
|
90
165
|
signing_key:
|
91
166
|
specification_version: 3
|
92
167
|
summary: Makes Apple TV compatible videos
|
93
|
-
test_files:
|
168
|
+
test_files:
|
169
|
+
- test/test_helper.rb
|