diff --git a/src/input-format.ts b/src/input-format.ts index 34ee4c4..8a6c352 100644 --- a/src/input-format.ts +++ b/src/input-format.ts @@ -598,6 +598,8 @@ export class HlsInputFormat extends InputFormat { throw new TypeError('HLS inputs require `InputOptions.source` to be a PathedSource or a ref to one.'); } + input._rootSource._usedForHls = true; + return true; } diff --git a/src/source.ts b/src/source.ts index c4eb8a2..733723f 100644 --- a/src/source.ts +++ b/src/source.ts @@ -80,6 +80,11 @@ export abstract class Source extends EventEmitter { _disposed = false; /** @internal */ _refCount = 0; + /** + * Used internally to mark if a source stems from an HLS reading operation. Used to suppress certain warnings. + * @internal + */ + _usedForHls = false; /** @internal */ private _sizePromise: Promise | null = null; @@ -270,9 +275,13 @@ export abstract class PathedSource extends Source { throw new TypeError('requestHandler must return or resolve to a Source or SourceRef.'); } - return result instanceof Source + const ref = result instanceof Source ? result.ref() : result; + + ref.source._usedForHls ||= this._usedForHls; + + return ref; }; if (result instanceof Promise) { @@ -794,19 +803,27 @@ export class UrlSource extends PathedSource { this._fileSizeDetermined = true; // Yes, this is correct even if file size is still null if (response.status !== 206) { - const origin = new URL( - this._url instanceof Request ? this._url.url : this._url, - typeof window !== 'undefined' ? window.location.href : undefined, - ).origin; + if (!this._usedForHls) { + const url = new URL( + this._url instanceof Request ? this._url.url : this._url, + typeof window !== 'undefined' ? window.location.href : undefined, + ); - if (origin !== 'null') { - if (!warnedOrigins.has(origin)) { - console.warn( - `HTTP server (origin ${origin}) did not respond to a range request with 206 Partial` - + ' Content, meaning the entire resource will now be downloaded. To enable efficient media' - + ' file streaming across a network, please make sure your server supports range requests.', - ); - warnedOrigins.add(origin); + if ( + url.origin !== 'null' + // Don't show the warning for M3U8 playlist files, it's irrelevant for those + && !(url.pathname.endsWith('.m3u8') || url.pathname.endsWith('.m3u')) + ) { + if (!warnedOrigins.has(url.origin)) { + console.log(this._usedForHls, this._url, url.pathname); + console.warn( + `HTTP server (origin ${url.origin}) did not respond to a range request with 206 Partial` + + ' Content, meaning the entire resource will now be downloaded. To enable efficient' + + ' media file streaming across a network, please make sure your server supports' + + ' range requests.', + ); + warnedOrigins.add(url.origin); + } } } diff --git a/test/node/hls-input.test.ts b/test/node/hls-input.test.ts index 76578e8..7924eec 100644 --- a/test/node/hls-input.test.ts +++ b/test/node/hls-input.test.ts @@ -1,6 +1,6 @@ /* eslint-disable @stylistic/max-len */ import { ALL_FORMATS, BufferSource, EncodedPacketSink, Input, InputAudioTrack, InputVideoTrack, UrlSource } from 'mediabunny'; -import { expect, test } from 'vitest'; +import { expect, test, vi } from 'vitest'; import { HLS, HLS_FORMATS, HlsInputFormat } from '../../src/input-format.js'; import { assert, rejectAfter } from '../../src/misc.js'; import { CustomPathedSource } from '../../src/source.js'; @@ -718,7 +718,9 @@ test.concurrent('Advanced Apple HLS', { timeout: 30_000 }, async () => { } }); -test.concurrent('Live HLS', { timeout: 30_000 }, async () => { +test.concurrent.only('Live HLS', { timeout: 30_000 }, async () => { + const consoleSpy = vi.spyOn(console, 'warn'); + using input = new Input({ source: new UrlSource('https://stream.mux.com/v69RSHhFelSm4701snP22dYz2jICy4E4FUyk02rW4gxRM.m3u8'), formats: ALL_FORMATS, @@ -781,6 +783,9 @@ test.concurrent('Live HLS', { timeout: 30_000 }, async () => { rejectAfter(2000, 'Baby you make me smile'), ]); expect(metadataDuration).toBeGreaterThan((Date.now() / 1000) - 3600); + + // The server doesn't answer with range requests but since it's HLS we suppress that warning + expect(consoleSpy).not.toHaveBeenCalled(); }); test.concurrent('#EXT-X-I-FRAME-STREAM-INF tags are parsed properly', async () => {