Skip to content

Instantly share code, notes, and snippets.

@eagletmt
Last active December 18, 2015 16:19
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save eagletmt/5810946 to your computer and use it in GitHub Desktop.
Save eagletmt/5810946 to your computer and use it in GitHub Desktop.
SD -> HD または HD -> SD の切り替えがあるときに、HD または SD の先頭オフセットを見つける
#!/usr/bin/env ruby
# coding: utf-8
require 'open3'
require 'tempfile'
class Avconv
def initialize(path, bin = 'avconv')
@path = path
@bin = bin
@tempfile = Tempfile.new ['sd-hd', '.ts']
end
def skip(t)
do_skip t
out, err, statuses = Open3.capture3 @bin, '-i', @tempfile.path
err.lines
end
def cuttable?(t)
do_skip t
system @bin, '-loglevel', 'quiet', '-i', @tempfile.path, '-acodec', 'copy', '-vcodec', 'copy', '-f', 'mpegts', '-t', '20', '-y', File::NULL
end
def do_skip(t)
Open3.pipeline ['tail', '-c', "+#{188*t}", @path], ["head", '-c', '18800000', { out: @tempfile.path }]
end
end
def bsearch(lo, hi, left_p, right_p)
while lo < hi
mid = (lo + hi)/2
p [lo, hi, mid]
if left_p.call mid
hi = mid
elsif right_p.call mid
lo = mid+1
else
$stderr.puts "Error at mid=#{mid}"
lo = mid+1
#raise "Error at mid=#{mid}"
end
end
lo
end
SD_SIZE = '720x480'
HD_SIZE = '1440x1080'
MAIN_STREAM = 'mpeg2video'
hd_p = lambda do |lines|
lines.any? do |line|
line.include? MAIN_STREAM and line.include? HD_SIZE
end
end
sd_p = lambda do |lines|
lines.any? do |line|
line.include? MAIN_STREAM and line.include? SD_SIZE
end
end
path = ARGV[0] or exit 1
avconv = Avconv.new path
MAX_PACKETS = 200000
first_lines = avconv.skip 0
last_lines = avconv.skip MAX_PACKETS
left_p = nil, right_p = nil
if sd_p.call first_lines and hd_p.call last_lines
$stderr.puts "SD -> HD detected"
left_p = hd_p
right_p = sd_p
elsif hd_p.call first_lines and sd_p.call last_lines
$stderr.puts "HD -> SD detected"
left_p = sd_p
right_p = hd_p
end
if left_p.nil? or right_p.nil?
$stderr.puts "No switching is detected"
exit 0
end
ans = bsearch(
0,
MAX_PACKETS,
lambda { |t| lines = avconv.skip t; left_p.call lines and not right_p.call lines and avconv.cuttable? t },
lambda { |t| right_p.call avconv.skip(t) }
)
puts "tail -c +$[188*#{ans}] #{path}"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment