Last active
November 24, 2019 17:35
-
-
Save epk/4eb34caf388891bddf20b5846fff85a8 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# frozen_string_literal: true | |
require 'net/http' | |
require 'fileutils' | |
require 'tempfile' | |
require 'open3' | |
require 'set' | |
require 'parallel' | |
class Panopto | |
class << self | |
def download_chunks(endpoint, video_name) | |
uri = URI.parse(endpoint) | |
@base_request_uri = uri.request_uri.split("/")[0...-1] | |
@connection = Net::HTTP.new(uri.host, uri.port).tap do |client| | |
client.use_ssl = uri.scheme == 'https' | |
end | |
chunks = find_number_of_chunks(0, 1000) | |
FileUtils.mkdir_p(File.join("src", video_name)) | |
(0..chunks).each do |i| | |
chunk = "#{format('%05d', i)}.ts" | |
request_uri = @base_request_uri.dup | |
request_uri << chunk | |
request_uri = request_uri.join("/") | |
if File.file?(File.join("src", video_name, chunk)) | |
next | |
else | |
request = Net::HTTP::Get.new(request_uri) | |
response = @connection.request(request) | |
code = response.code.to_i | |
if code == 200 | |
File.open(File.join("src", video_name, chunk), "w") { |file| file.puts response.body } | |
end | |
end | |
puts("#{video_name}: #{i}/#{chunks} downloaded") | |
end | |
end | |
def concat_chunks(video_name) | |
return if File.file?("#{video_name.chomp}.mp4") | |
list = [] | |
files = Dir.entries(File.join("src", video_name)).reject { |f| File.directory?(f) } | |
files.sort.each do |file| | |
list << "file '#{File.expand_path(File.join('src', video_name, file))}'" | |
end | |
FileUtils.rm("list.txt") if File.file?("list.txt") | |
File.open("list.txt", "w") { |file| file.puts list.join("\n") } | |
Open3.popen3("ffmpeg", | |
"-safe", "0", | |
"-f", "concat", "-i", "list.txt", | |
"-c", "copy", "#{video_name.chomp}.mp4") do |_stdin, stdout, _stderr, _thread| | |
puts stdout.read.chomp | |
end | |
true | |
ensure | |
FileUtils.rm("list.txt") if File.file?("list.txt") | |
end | |
def transcribe(video_name) | |
# autosub -i Lecture_1.mp4 -S en-ca | |
Open3.popen3("autosub", | |
"-i", "#{video_name.chomp}.mp4", | |
"-S", "en-ca") do |_stdin, stdout, _stderr, _thread| | |
puts stdout.read.chomp | |
end | |
# ffmpeg -i infile.mp4 -i infile.srt -c copy -c:s mov_text outfile.mp4 | |
Open3.popen3("ffmpeg", | |
"-i", "#{video_name.chomp}.mp4", | |
"-i", "#{video_name.chomp}.en-ca.srt", | |
"-c", "copy", | |
"-c:s", "mov_text", | |
"#{video_name.chomp}_subtitled.mp4") do |_stdin, stdout, _stderr, _thread| | |
puts stdout.read.chomp | |
end | |
true | |
end | |
private | |
def find_number_of_chunks(lower, upper) | |
mid = lower + (upper - lower) / 2 | |
valid = poll_endpoint_for_chunk(mid) | |
if valid && !poll_endpoint_for_chunk(mid + 1) | |
return mid | |
elsif valid && poll_endpoint_for_chunk(mid + 1) | |
return find_number_of_chunks(mid, upper) | |
else | |
return find_number_of_chunks(lower, mid) | |
end | |
end | |
def poll_endpoint_for_chunk(counter) | |
chunk = "#{format('%05d', counter)}.ts" | |
request_uri = @base_request_uri.dup | |
request_uri << chunk | |
request_uri = request_uri.join("/") | |
request = Net::HTTP::Head.new(request_uri) | |
response = @connection.request(request) | |
code = response.code.to_i | |
code == 200 | |
end | |
end | |
end | |
begin | |
list = [] | |
if list.to_set.length != list.length | |
raise("Duplicate items in array") | |
end | |
Parallel.each_with_index(list) do |url, index| | |
Panopto.download_chunks(url, "Lecture_#{index + 1}") | |
end | |
list.each_with_index do |_, index| | |
Panopto.concat_chunks("Lecture_#{index + 1}") | |
end | |
list.each_with_index do |_, index| | |
Panopto.transcribe("Lecture_#{index + 1}") | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment