about summary refs log tree commit homepage
path: root/lib/dtas/source/av.rb
diff options
context:
space:
mode:
Diffstat (limited to 'lib/dtas/source/av.rb')
-rw-r--r--lib/dtas/source/av.rb49
1 files changed, 36 insertions, 13 deletions
diff --git a/lib/dtas/source/av.rb b/lib/dtas/source/av.rb
index 804a66b..1de0a72 100644
--- a/lib/dtas/source/av.rb
+++ b/lib/dtas/source/av.rb
@@ -11,9 +11,12 @@ class DTAS::Source::Av # :nodoc:
 
   include DTAS::Source::File
 
+  AStream = Struct.new(:duration, :channels, :rate)
+
   AV_DEFAULTS = COMMAND_DEFAULTS.merge(
     "command" =>
-      'avconv -v error $SSPOS -i "$INFILE" -f sox - | sox -p $SOXFMT - $RGFX',
+      'avconv -v error $SSPOS -i "$INFILE" $AMAP -f sox - |' \
+      'sox -p $SOXFMT - $RGFX',
     "comments" => nil,
   )
 
@@ -42,24 +45,23 @@ class DTAS::Source::Av # :nodoc:
     @comments = {}
     err = ""
     s = qx(%W(avprobe -show_streams -show_format #@infile), err: err)
+    @astreams = []
     s.scan(%r{^\[STREAM\]\n(.*?)\n\[/STREAM\]\n}m) do |_|
       stream = $1
       # XXX what to do about multiple streams?
       if stream =~ /^codec_type=audio$/
-        duration = channels = rate = nil
-        stream =~ /^duration=([\d\.]+)\s*$/m and duration = $1.to_f
-        stream =~ /^channels=(\d)\s*$/m and channels = $1.to_i
-        stream =~ /^sample_rate=([\d\.]+)\s*$/m and rate = $1.to_i
-        if channels > 0 && rate > 0
-          @duration = duration
-          @format.channels = channels
-          @format.rate = rate
-        end
+        as = AStream.new
+        index = nil
+        stream =~ /^index=(\d+)\s*$/m and index = $1.to_i
+        stream =~ /^duration=([\d\.]+)\s*$/m and as.duration = $1.to_f
+        stream =~ /^channels=(\d)\s*$/m and as.channels = $1.to_i
+        stream =~ /^sample_rate=([\d\.]+)\s*$/m and as.rate = $1.to_i
+        @astreams[index] = as if as.channels > 0 && as.rate > 0
       end
     end
     s.scan(%r{^\[FORMAT\]\n(.*?)\n\[/FORMAT\]\n}m) do |_|
       f = $1
-      f =~ /^duration=([\d\.]+)\s*$/m and @duration ||= $1.to_f
+      f =~ /^duration=([\d\.]+)\s*$/m and @duration = $1.to_f
       # TODO: multi-line/multi-value/repeated tags
       f.gsub!(/^TAG:([^=]+)=(.*)$/i) { |_| @comments[$1.upcase] = $2 }
     end
@@ -71,10 +73,31 @@ class DTAS::Source::Av # :nodoc:
     sprintf("-ss %0.9g", samples / @format.rate)
   end
 
-  def spawn(format, rg_state, opts)
+  def spawn(player_format, rg_state, opts)
     raise "BUG: #{self.inspect}#spawn called twice" if @to_io
-    e = @format.to_env
+    amap = nil
+    found_as = nil
+
+    # try to find an audio stream which matches our channel count
+    # we need to set @format for sspos() down below
+    @astreams.each_with_index do |as, index|
+      if as && as.channels == player_format.channels
+        @format.channels = as.channels
+        @format.rate = as.rate
+        found_as = as
+        amap = "-map 0:#{index}"
+      end
+    end
+    unless found_as
+      first_as = @astreams.compact[0]
+      if first_as
+        @format.channels = found_as.channels
+        @format.rate = found_as.rate
+      end
+    end
+    e = player_format.to_env
     e["INFILE"] = @infile
+    e["AMAP"] = amap
 
     # make sure these are visible to the "current" command...
     @env["SSPOS"] = @offset ? sspos(@offset) : nil