diff --git a/app/models/master_file.rb b/app/models/master_file.rb index d76ae81e2e..a0ce72f908 100644 --- a/app/models/master_file.rb +++ b/app/models/master_file.rb @@ -585,7 +585,7 @@ def create_frame_source_hls_temp_file(offset) # Fixes https://github.com/avalonmediasystem/avalon/issues/3474 target_location = File.basename(details[:location]).split('?')[0] target = File.join(Dir.tmpdir, target_location) - File.open(target,'wb') { |f| open(details[:location]) { |io| f.write(io.read) } } + File.open(target,'wb') { |f| URI.open(details[:location]) { |io| f.write(io.read) } } return target, details[:offset] end diff --git a/lib/avalon/m3u8_reader.rb b/lib/avalon/m3u8_reader.rb index addf7ad4a8..ddee653eab 100644 --- a/lib/avalon/m3u8_reader.rb +++ b/lib/avalon/m3u8_reader.rb @@ -37,7 +37,7 @@ def initialize(playlist, base = '', recursive: true) @base = base @playlist = { files: [], playlists: [] } tags = {} - playlist.each do |l| + playlist.each_line do |l| line = l.chomp if line =~ /^#EXTM3U/ # ignore diff --git a/spec/lib/avalon/m3u8_read_spec.rb b/spec/lib/avalon/m3u8_read_spec.rb index 562749e9bd..02beab4571 100644 --- a/spec/lib/avalon/m3u8_read_spec.rb +++ b/spec/lib/avalon/m3u8_read_spec.rb @@ -16,21 +16,84 @@ require 'avalon/m3u8_reader' describe Avalon::M3U8Reader do - let(:m3u_file) { File.expand_path('../../../fixtures/The_Fox.mp4.m3u',__FILE__) } - let(:m3u) { Avalon::M3U8Reader.read(m3u_file) } + let(:m3u_filename) { File.expand_path('../../../fixtures/The_Fox.mp4.m3u',__FILE__) } + let(:m3u) { Avalon::M3U8Reader.read(m3u_filename) } let(:framespec) { m3u.at(127000) } - it "should know how many files it has" do - expect(m3u.files.length).to eq(23) + context 'with a filepath' do + it "should know how many files it has" do + expect(m3u.files.length).to eq(23) + end + + it "should know its duration" do + expect(m3u.duration.round(2)).to eq(225.14) + end + + it "should be able to locate a frame" do + expect(framespec[:location]).to match(%r{/The_Fox.mp4-012.ts$}) + expect(framespec[:filename]).to eq('The_Fox.mp4-012.ts') + expect(framespec[:offset].round(2)).to eq(6818.91) + end + end + + context 'with a url' do + let(:m3u_url) { Rails.application.routes.url_helpers.hls_manifest_master_file_url(id: 1, quality: "auto") } + let(:m3u) { Avalon::M3U8Reader.read(m3u_url) } + + before do + stub_request(:get, m3u_url).to_return(body: File.read(m3u_filename)) + end + + it "should know how many files it has" do + expect(m3u.files.length).to eq(23) + end + + it "should know its duration" do + expect(m3u.duration.round(2)).to eq(225.14) + end + + it "should be able to locate a frame" do + expect(framespec[:location]).to match(%r{/The_Fox.mp4-012.ts$}) + expect(framespec[:filename]).to eq('The_Fox.mp4-012.ts') + expect(framespec[:offset].round(2)).to eq(6818.91) + end end - it "should know its duration" do - expect(m3u.duration.round(2)).to eq(225.14) + context 'with a file' do + let(:m3u_file) { File.open(m3u_filename) } + let(:m3u) { Avalon::M3U8Reader.read(m3u_file) } + + it "should know how many files it has" do + expect(m3u.files.length).to eq(23) + end + + it "should know its duration" do + expect(m3u.duration.round(2)).to eq(225.14) + end + + it "should be able to locate a frame" do + expect(framespec[:location]).to match(%r{/The_Fox.mp4-012.ts$}) + expect(framespec[:filename]).to eq('The_Fox.mp4-012.ts') + expect(framespec[:offset].round(2)).to eq(6818.91) + end end - it "should be able to locate a frame" do - expect(framespec[:location]).to match(%r{/The_Fox.mp4-012.ts$}) - expect(framespec[:filename]).to eq('The_Fox.mp4-012.ts') - expect(framespec[:offset].round(2)).to eq(6818.91) + context 'with a string' do + let(:m3u_file_contents) { File.read(m3u_filename) } + let(:m3u) { Avalon::M3U8Reader.read(m3u_file_contents) } + + it "should know how many files it has" do + expect(m3u.files.length).to eq(23) + end + + it "should know its duration" do + expect(m3u.duration.round(2)).to eq(225.14) + end + + it "should be able to locate a frame" do + expect(framespec[:location]).to match(%r{/The_Fox.mp4-012.ts$}) + expect(framespec[:filename]).to eq('The_Fox.mp4-012.ts') + expect(framespec[:offset].round(2)).to eq(6818.91) + end end end diff --git a/spec/models/master_file_spec.rb b/spec/models/master_file_spec.rb index fd9b236467..da182c0af6 100644 --- a/spec/models/master_file_spec.rb +++ b/spec/models/master_file_spec.rb @@ -632,13 +632,24 @@ context 'when derivatives are not accessible' do let(:high_derivative_locator) { FileLocator.new(video_master_file.derivatives.where(quality_ssi: 'high').first.absolute_location) } - let(:hls_temp_file) { "/tmp/temp_segment.ts" } + let(:hls_file) { "temp_segment.ts" } + let(:hls_url) { "http://streaming.server.com/path/#{hls_file}" } + let(:reader) { double(Avalon::M3U8Reader) } + let(:m3u8) { "HLSDATA" } + + before do + stub_request(:get, hls_url).to_return(body: m3u8) + allow(Avalon::M3U8Reader).to receive(:read).and_return(reader) + allow(reader).to receive(:at).and_return({ location: hls_url, filename: hls_file, offset: 0 }) + end it 'falls back to HLS' do - expect(video_master_file).to receive(:create_frame_source_hls_temp_file).and_return(hls_temp_file) - expect(File).to receive(:exist?).with(high_derivative_locator.location).and_return(false) + #expect(video_master_file).to receive(:create_frame_source_hls_temp_file).and_return(hls_temp_file) + allow(File).to receive(:exist?).and_call_original + allow(File).to receive(:exist?).with(high_derivative_locator.location).and_return(false) expect(source[:source]).to eq '/tmp/temp_segment.ts' expect(source[:non_temp_file]).to eq false + expect(File.read(source[:source])).to eq m3u8 end end end