#!/usr/bin/env ruby require 'pit' require 'niconico' require 'pathname' require 'open3' def alt_title(video_id) xml = open("http://ext.nicovideo.jp/api/getthumbinfo/#{video_id}").read xml.scan(%r|(.*)|m).flatten.first || video_id end if ARGV.size == 0 $stderr.puts "usage: nicodl [URL...]" exit -1 end account = Pit::get('nicovideo', :require => { :id => 'your nicovideo id', :pass => 'your nicovideo password' }) nico = Niconico.new(account[:id], account[:pass]) retry_count = 0 begin nico.login rescue Mechanize::ResponseReadError retry_count += 1 if retry_count < 10 puts "login faiure. retring(#{retry_count})" sleep 5 retry end $stderr.puts 'login faiure.' exit -2 end ARGV.each do |player_url| video_id = Pathname(URI(player_url).path).basename.to_s begin # downloading video video = nico.video(video_id) file = "#{video.title || alt_title(video_id)}.#{video.type}".gsub(%r([\\/\?:*"'><|]), '_') open(file, 'wb:ASCII-8BIT') do |o| video.get_video{|body|o.write(body)} end rescue Mechanize::ResponseCodeError, Errno::EISDIR # live streaming time-shift live = nico.live(video_id) begin live.rtmpdump_commands(video_id).each_with_index do |cmd, i| src = "#{video_id}-#{i+1}.flv" dst = "#{live.title.gsub(%r([\\/\?:*"'><|]), '_')}-#{i+1}.mp4" unless File.exist?(src) cmd[cmd.index('-o') + 1] = "./#{src}" begin o, e, s = Open3.capture3(*cmd) unless s.exitstatus == 0 $stderr.puts e next end rescue Errno::ENOENT # rtmdump command not found $stderr.puts $! exit 1 end else $stderr.puts "#{src} is existent. skipping." end cmd = 'ffmpeg' args = ['-i', src, '-acodec', 'copy', '-vcodec', 'copy', dst] begin o, e, s = Open3.capture3(cmd, *args) unless s.exitstatus == 0 $stderr.puts e next end File.delete(src) rescue Errno::ENOENT if cmd == 'avconv' $stderr.puts "ffmpeg or avconv not found." else # retry with avconv command instead of ffmpeg cmd = 'avconv' retry end end end rescue Niconico::Live::TicketRetrievingFailed $stderr.puts $! exit 2 end end end