rtrack 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 2d02c55bbd7729e987cdcb9f0c13b425ae9b3f7d
4
+ data.tar.gz: 8ffdfc4796d22c2703aff633bfc0cbbba2dd6e1a
5
+ SHA512:
6
+ metadata.gz: 54457b9e1da6673b26a189067266bdc90d6226a278e05d196491b93a111bd7c8d93c190fd231992447f11080473258487b46418755edd65d223e9a998183547d
7
+ data.tar.gz: 9b9c94fb0aa422bb8d8e1c68004ff1e8e2aff86a761a71f71b9386e82321b21572ed5d9fd1523fc48525f6105d41563ac8c34fc8eccf74ac05cadd5846b1de31
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in rtrack.gemspec
4
+ gemspec
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 marcwebbie
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,133 @@
1
+ # Rtrack
2
+
3
+ RTrack is a object-oriented wrapper around ffmpeg to manipulate audiofiles easily from ruby code.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'rtrack'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install rtrack
18
+
19
+ ## Usage
20
+
21
+ Open a wave file
22
+
23
+ ```ruby
24
+ require 'rtrack'
25
+
26
+ song = AudioTrack.from_file "never_gonna_give_you_up.wav"
27
+ ```
28
+
29
+ ...or a mp3 file
30
+
31
+
32
+ ```ruby
33
+ require 'rtrack'
34
+
35
+ song = AudioTrack.from_file "never_gonna_give_you_up.mp3"
36
+ ```
37
+
38
+ ... or an ogg, or flv, or [anything else ffmpeg supports](http://www.ffmpeg.org/general.html#File-Formats)
39
+
40
+ ```ruby
41
+ ogg_version = AudioTrack.from_file "never_gonna_give_you_up.ogg"
42
+ flv_version = AudioTrack.from_file "never_gonna_give_you_up.flv"
43
+ mp4_version = AudioTrack.from_file "never_gonna_give_you_up.mp4"
44
+ wma_version = AudioTrack.from_file "never_gonna_give_you_up.wma"
45
+ aac_version = AudioTrack.from_file "never_gonna_give_you_up.aiff"
46
+ ```
47
+
48
+ You can concatenate multiple AudioTracks together
49
+
50
+ ```ruby
51
+ song_one = AudioTrack.from_file "one_love.mp3"
52
+ song_two = AudioTrack.from_file "jamming.ogg"
53
+
54
+ song_three = song_one + song_two
55
+
56
+ song_four = song_one + song_two + song_three + AudioTrack.from_file "buffallo_soldiers.mp3"
57
+ ```
58
+
59
+ Get a slice of a track, first 10 seconds
60
+
61
+ ```ruby
62
+ song = AudioTrack.from_file "mozart.mp3"
63
+ slice = song[10000] # rtrack works on milliseconds
64
+ ```
65
+
66
+ Wonder how long is that song?
67
+
68
+ ```
69
+ song = AudioTrack.from_file "jamming.mp3"
70
+ puts song.seconds
71
+ ```
72
+
73
+ Repeat track 4 times
74
+
75
+ ```ruby
76
+ beat = AudioTrack.from_file "beat.wav"
77
+ remix = beat * 4
78
+ ```
79
+
80
+ Save the result to disk
81
+
82
+ ```ruby
83
+ remix.export "remix.mp3", "mp3"
84
+ # or
85
+ remix.save "remix.mp3", "mp3"
86
+ ```
87
+
88
+ Save the results with bitrate
89
+
90
+ ```ruby
91
+ remix.export "remix.mp3", "mp3", "192k"
92
+ ```
93
+
94
+ ## Examples
95
+
96
+ Let's suppose you have plenty of `mp4` videos that you'd like to convert to
97
+ `mp3` so you can listen on your mp3 player on the road.
98
+
99
+ ```ruby
100
+ require "rtrack"
101
+
102
+ Dir[Dir.home + "/Videos/*.mp4"].each do |video_path|
103
+ video_name = File.basename(video_path, File.extname(video_path))
104
+ puts "converting #{video_name}"
105
+ song = AudioTrack.from_file video_path
106
+ song.export "#{video_name}.mp3"
107
+ end
108
+ ```
109
+
110
+ ## Dependencies
111
+
112
+ Requires ffmpeg or avconv for encoding and decoding.
113
+
114
+ - ffmpeg (http://www.ffmpeg.org/)
115
+
116
+ -OR-
117
+
118
+ - avconv (http://libav.org/)
119
+
120
+ ## Trivia
121
+
122
+ + RTrack is inspired by [pydub](http://www.github.com/jiaaro/pydub) and [jquery](http://www.jquery.com)
123
+ + As in pydub all AudioTrack objects are [immutable](http://rubylearning.com/satishtalim/mutable_and_immutable_objects.html)
124
+ + As in jquery you can chain operations using AudioTrack objects
125
+
126
+
127
+ ## Contributing
128
+
129
+ 1. Fork it ( http://github.com/marcwebbie/rtrack/fork )
130
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
131
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
132
+ 4. Push to the branch (`git push origin my-new-feature`)
133
+ 5. Create new Pull Request
@@ -0,0 +1,9 @@
1
+ require "bundler/gem_tasks"
2
+ require "rake/testtask"
3
+
4
+
5
+ Rake::TestTask.new do |t|
6
+ t.libs << 'test'
7
+ end
8
+
9
+ task :default => :test
@@ -0,0 +1,58 @@
1
+ require "tempfile"
2
+
3
+ require "rtrack/version"
4
+ require "rtrack/transcoder"
5
+
6
+ class AudioTrack
7
+ attr_reader :wavefile, :duration
8
+
9
+ def initialize (wavefile, duration)
10
+ @wavefile = wavefile
11
+ @duration = duration
12
+ end
13
+
14
+ def self.from_file(infile)
15
+ if not (File.exists? infile)
16
+ fail StandardError, "Couldn't find file from path: #{infile}"
17
+ end
18
+ infile = File.open(infile)
19
+ wavefile = Tempfile.new ['','.wav']
20
+ duration = RTrack::Transcoder.to_wave(infile.path, wavefile.path)
21
+ AudioTrack.new wavefile, duration
22
+ end
23
+
24
+ def seconds
25
+ @duration / 1000
26
+ end
27
+
28
+ def path
29
+ @wavefile.path
30
+ end
31
+
32
+ def [](slice_range)
33
+ if not slice_range.class == Range
34
+ fail StandardError, "Invalid slice was given: #{slice_range}"
35
+ end
36
+
37
+ slice_start, slice_end = slice_range.min, slice_range.max
38
+ new_wavefile = Tempfile.new ['','.wav']
39
+ duration = RTrack::Transcoder.to_slice(@wavefile.path,
40
+ new_wavefile.path,
41
+ slice_start,
42
+ slice_end)
43
+
44
+ AudioTrack.new new_wavefile, duration
45
+ end
46
+
47
+ def +(other)
48
+ info = RTrack::Transcoder.concat @wavefile.path, other.wavefile.path
49
+ AudioTrack.new info["wavefile"], info["duration"]
50
+ end
51
+
52
+ def export(outpath, format="mp3", bitrate="128k")
53
+ return_code = RTrack::Transcoder.export(@wavefile.path, outpath, format, bitrate)
54
+ return_code
55
+ end
56
+
57
+ alias_method :save, :export
58
+ end
@@ -0,0 +1,74 @@
1
+
2
+ module RTrack
3
+ class Transcoder
4
+ BIN = "ffmpeg"
5
+ PROBER = "ffprobe"
6
+
7
+ def self._clean_output output
8
+ output.encode('UTF-8', 'binary', invalid: :replace, undef: :replace, replace: '')
9
+ end
10
+
11
+ def self.bin
12
+ @@bin
13
+ end
14
+
15
+ def self.to_milliseconds(hours, mins, secs, msecs=0)
16
+ (hours * 3600000) + (mins * 60000) + (secs * 1000) + msecs
17
+ end
18
+
19
+ def self.parse_duration(output)
20
+ begin
21
+ output = self._clean_output output
22
+ time_string = output.scan(/time\=(\d+:\d+:\d+\.\d+)/).last.last
23
+ rescue NoMethodError
24
+ raise StandardError, "Couldn't parse duration from transcoder output"
25
+ end
26
+
27
+ mobj = time_string.match(/(?<hours>\d+):(?<mins>\d+):(?<secs>\d+)\.(?<msecs>\d+)/)
28
+ hours = mobj["hours"].to_i
29
+ mins = mobj["mins"].to_i
30
+ secs = mobj["secs"].to_i
31
+ msecs = mobj["msecs"].ljust(3, "0").to_i
32
+
33
+ to_milliseconds hours, mins, secs, msecs
34
+ end
35
+
36
+ def self.to_wave(infile_path, wavefile_path)
37
+ cmd = "#{self::BIN} -y -i #{infile_path} -f wav #{wavefile_path} 2>&1"
38
+ output = `#{cmd}`
39
+ self.parse_duration output
40
+ end
41
+
42
+ def self.to_slice(infile_path, wavefile_path, start, to)
43
+ cmd = "#{self::BIN} -y -i #{infile_path} -ss #{start} -to #{to} -f wav #{wavefile_path} 2>&1"
44
+ output = `#{cmd}`
45
+ self.parse_duration output
46
+ end
47
+
48
+ def self.concat(media_one, media_two)
49
+ new_wavefile = Tempfile.new ['','.wav']
50
+ cmd = "#{self::BIN} -y -i #{media_one} -i #{media_two} -filter_complex '[0:0][1:0]concat=n=2:v=0:a=1[out]' -map '[out]' #{new_wavefile.path} 2>&1"
51
+ output = `#{cmd}`
52
+ duration = self.parse_duration output
53
+ {"wavefile" => new_wavefile, "duration" => duration}
54
+ end
55
+
56
+ def self.is_media?(filepath)
57
+ cmd = "#{self::PROBER} #{filepath} >/dev/null 2>&1"
58
+ `#{cmd}`
59
+ $?.success?
60
+ end
61
+
62
+ def self.export(inpath, outpath, format, bitrate)
63
+ cmd = "#{self::BIN} -y -i #{inpath} -f #{format} -b:a #{bitrate} #{outpath} 2>&1"
64
+ `#{cmd}`
65
+ $?.success?
66
+ end
67
+
68
+ def self.info mediapath
69
+ cmd = "#{self::PROBER} -v quiet -print_format json -show_format -show_streams #{mediapath}"
70
+ output = `#{cmd}`
71
+ JSON::parse output
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,3 @@
1
+ module Rtrack
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,24 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'rtrack/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "rtrack"
8
+ spec.version = Rtrack::VERSION
9
+ spec.authors = ["marcwebbie"]
10
+ spec.email = ["marcwebbie@gmail.com"]
11
+ spec.summary = "RTrack is a object-oriented wrapper around ffmpeg to manipulate audiofiles easily from ruby code."
12
+ spec.description = "RTrack is a object-oriented wrapper around ffmpeg to manipulate audiofiles easily from ruby code."
13
+ spec.homepage = "http://github.com/marcwebbie/rtrack"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.5"
22
+ spec.add_development_dependency "rake"
23
+ spec.add_development_dependency "pry"
24
+ end
Binary file
File without changes
Binary file
Binary file
Binary file
Binary file
@@ -0,0 +1,99 @@
1
+ require 'test/unit'
2
+ require 'tempfile'
3
+
4
+ require 'rtrack'
5
+ require 'rtrack/transcoder'
6
+
7
+ class Audiorack_Tests < Test::Unit::TestCase
8
+ def setup
9
+ @track = AudioTrack.from_file "test/data/test.mp3"
10
+ end
11
+
12
+ def test_instantiate_audio_track_from_file
13
+ test_track = AudioTrack.from_file "test/data/test.mp3"
14
+ assert_not_nil test_track
15
+ assert_equal test_track.class, AudioTrack
16
+ end
17
+
18
+ def test_from_file_throw_exception_when_wrong_infile_path_is_given
19
+ assert_raises(StandardError) do
20
+ test_track = AudioTrack.from_file "test/data/wrong_path.mp3"
21
+ assert_not_nil test_track
22
+ end
23
+ end
24
+
25
+ def test_audio_track_has_a_not_nil_wavefile_from_given_infile
26
+ test_track = AudioTrack.from_file "test/data/test.mp3"
27
+ assert_not_nil test_track.wavefile
28
+ end
29
+
30
+ def test_from_file_returns_audio_track_with_valid_wavefile
31
+ test_track = AudioTrack.from_file "test/data/test.mp3"
32
+ wavefile = test_track.wavefile
33
+ assert_respond_to wavefile, "path"
34
+ assert_equal File.exists?(wavefile.path), true
35
+ assert_equal wavefile.path.end_with?(".wav"), true
36
+ end
37
+
38
+ def test_from_file_returns_audio_track_with_expected_duration
39
+ test_track = AudioTrack.from_file "test/data/test.mp3"
40
+ expected_duration = 10040
41
+ assert_respond_to test_track, "duration"
42
+ assert_equal expected_duration, test_track.duration
43
+
44
+ test_track = AudioTrack.from_file "test/data/test2.mp3"
45
+ expected_duration = 5040
46
+ assert_respond_to test_track, "duration"
47
+ assert_equal expected_duration, test_track.duration
48
+ end
49
+
50
+ def test_duration_seconds_match_duration
51
+ assert_respond_to @track, "seconds"
52
+ expected_seconds = @track.duration/1000
53
+ assert_equal expected_seconds, @track.seconds
54
+ end
55
+
56
+ def test_slice_from_song_has_expected_duration
57
+ assert_respond_to @track, "[]"
58
+ expected_seconds = Random.rand(1..10)
59
+
60
+ slice = AudioTrack.from_file(@track.path)[0..expected_seconds]
61
+ assert_equal slice.seconds, expected_seconds
62
+ slice = AudioTrack.from_file(@track.path)[0...expected_seconds]
63
+ assert_equal slice.seconds, expected_seconds-1
64
+ end
65
+
66
+ def test_slice_operation_throws_exception_when_invalid_slice_range_is_given
67
+ assert_raises(StandardError) do
68
+ @track[nil]
69
+ end
70
+
71
+ assert_raises(StandardError) do
72
+ @track[50]
73
+ end
74
+ end
75
+
76
+ def test_concatenate_two_audio_tracks_has_duration_equal_to_sum_of_durations
77
+ track_one = AudioTrack.from_file("test/data/test.mp3")
78
+ track_two = AudioTrack.from_file("test/data/test2.mp3")
79
+
80
+ assert_respond_to track_one, "+"
81
+ track_three = track_one + track_two
82
+ assert_equal track_three.seconds, track_one.seconds + track_two.seconds
83
+ end
84
+
85
+ def test_export_track
86
+ remix = @track + @track
87
+ destination_file = Tempfile.new ["",".mp3"]
88
+
89
+ assert_respond_to remix, "export"
90
+ assert_equal false, RTrack::Transcoder.is_media?(destination_file.path)
91
+ remix.export destination_file.path
92
+ assert_equal true, RTrack::Transcoder.is_media?(destination_file.path)
93
+ end
94
+
95
+ def test_save_is_same_as_export
96
+ assert_respond_to @track, "save"
97
+ assert_equal @track.method(:save), @track.method(:export)
98
+ end
99
+ end
@@ -0,0 +1,31 @@
1
+ require 'test/unit'
2
+ require 'tempfile'
3
+ require 'json'
4
+
5
+ require 'rtrack'
6
+
7
+ class Transcoder_Tests < Test::Unit::TestCase
8
+ def test_transcoder_raises_standard_error_when_missing_time_from_transcoder_output
9
+ assert_raises(StandardError) do
10
+ RTrack::Transcoder.parse_duration "bad output"
11
+ end
12
+ end
13
+
14
+ def test_trascoder_check_if_mp3_is_valid_media
15
+ assert_equal true, RTrack::Transcoder.is_media?("test/data/test2.mp3")
16
+ assert_equal false, RTrack::Transcoder.is_media?("test/data/bad.mp3")
17
+ end
18
+
19
+ def test_transcoder_parse_duration_returns_expected_milliseconds
20
+ mock_output = "time=00:00:10.04"
21
+ expected_milliseconds = 10040
22
+ assert_equal expected_milliseconds, RTrack::Transcoder.parse_duration(mock_output)
23
+ end
24
+
25
+ def test_transcoder_info_returns_expected_hash_with_info_about_media
26
+ assert_respond_to RTrack::Transcoder, "info"
27
+ info = RTrack::Transcoder.info "test/data/test3.mp3"
28
+ assert_equal true, info.keys.include?("streams"), "info doesn't contain streams"
29
+ assert_equal true, info.keys.include?("format"), "info doens't contain formats"
30
+ end
31
+ end
metadata ADDED
@@ -0,0 +1,113 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rtrack
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - marcwebbie
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-04-01 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.5'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.5'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: pry
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ description: RTrack is a object-oriented wrapper around ffmpeg to manipulate audiofiles
56
+ easily from ruby code.
57
+ email:
58
+ - marcwebbie@gmail.com
59
+ executables: []
60
+ extensions: []
61
+ extra_rdoc_files: []
62
+ files:
63
+ - ".gitignore"
64
+ - Gemfile
65
+ - LICENSE.txt
66
+ - README.md
67
+ - Rakefile
68
+ - lib/rtrack.rb
69
+ - lib/rtrack/transcoder.rb
70
+ - lib/rtrack/version.rb
71
+ - rtrack.gemspec
72
+ - test/data/bach.ogg
73
+ - test/data/bad.mp3
74
+ - test/data/party.mp3
75
+ - test/data/test.mp3
76
+ - test/data/test2.mp3
77
+ - test/data/test3.mp3
78
+ - test/test_rtrack.rb
79
+ - test/test_transcoder.rb
80
+ homepage: http://github.com/marcwebbie/rtrack
81
+ licenses:
82
+ - MIT
83
+ metadata: {}
84
+ post_install_message:
85
+ rdoc_options: []
86
+ require_paths:
87
+ - lib
88
+ required_ruby_version: !ruby/object:Gem::Requirement
89
+ requirements:
90
+ - - ">="
91
+ - !ruby/object:Gem::Version
92
+ version: '0'
93
+ required_rubygems_version: !ruby/object:Gem::Requirement
94
+ requirements:
95
+ - - ">="
96
+ - !ruby/object:Gem::Version
97
+ version: '0'
98
+ requirements: []
99
+ rubyforge_project:
100
+ rubygems_version: 2.2.2
101
+ signing_key:
102
+ specification_version: 4
103
+ summary: RTrack is a object-oriented wrapper around ffmpeg to manipulate audiofiles
104
+ easily from ruby code.
105
+ test_files:
106
+ - test/data/bach.ogg
107
+ - test/data/bad.mp3
108
+ - test/data/party.mp3
109
+ - test/data/test.mp3
110
+ - test/data/test2.mp3
111
+ - test/data/test3.mp3
112
+ - test/test_rtrack.rb
113
+ - test/test_transcoder.rb