open

expect fun open(path: String): MediaSource

Open a local file or URL.

This is a blocking call. Network URLs perform I/O inside the native open, so call it from a background dispatcher (Dispatchers.IO or your media dispatcher). Never call it on the UI thread.


expect fun open(path: String, options: Map<String, String>, interrupt: OpenInterrupt? = null): MediaSource

Open with pre-open options: pairs applied between allocation and open, the only moment probesize, fflags and format forcing can act. Keys FFmpeg does not consume are reported through unusedOpenOptions, never silently dropped.

interrupt lets another thread stop this open while it runs, and then stays with the returned source; see OpenInterrupt. The open fails with FFmpegError.Interrupted.


expect fun open(io: MediaByteSource, options: Map<String, String> = emptyMap(), interrupt: OpenInterrupt? = null, url: String? = null, mimeType: String? = null, nestedOpener: MediaByteOpener? = null): MediaSource

Open over caller-supplied bytes: FFmpeg demuxes whatever io reads, with no path involved. The returned source OWNS io and closes it when it closes. Pre-open options and interrupt behave exactly like the path overload's. Blocking, like every open here: call it off the UI thread, and expect io's own read latency to shape the open time.

Three optional parameters say where the bytes come from:

  • url is the address that io reads. The bytes still come from io. FFmpeg uses the address to recognise the format, as it uses a file name, and to resolve the relative addresses inside the media, unless io names its MediaByteSource.location, which they then resolve against, as after a redirect.

  • mimeType is the type the bytes arrived with, such as a server's Content-Type. The probe uses it. An HLS playlist whose url does not end in .m3u8 or .m3u opens only with an HLS type, such as application/vnd.apple.mpegurl.

  • nestedOpener opens the other addresses that the media names, such as the segments and keys of an HLS playlist. Without it, FFmpeg opens those addresses with its own protocols, which have no https.

An HLS stream over https needs url and nestedOpener, and mimeType too when url does not end in .m3u8:

val source = MediaSource.open(
io = playlistBytes,
url = "https://cdn.example/live/index",
mimeType = "application/vnd.apple.mpegurl",
nestedOpener = { address -> if (address.startsWith("https://cdn.example/")) fetch(address) else null },
)

On the web, io is read as FFmpeg asks for its bytes wherever a read may block, which is a Worker, so it can answer with a synchronous range request, and it is closed when the returned source closes. On a page's main thread, where nothing may block, it is read whole into the codec module's memory during the open, up to 512 MB, and closed then. Every source that nestedOpener returns is read whole as soon as the opener returns it, and closed. The opener has to answer at once as well, which on a page means bytes it already holds, and in a Worker can mean a synchronous request.

actual fun open(path: String): MediaSource

Open a local file or URL.

This is a blocking call. Network URLs perform I/O inside the native open, so call it from a background dispatcher (Dispatchers.IO or your media dispatcher). Never call it on the UI thread.


actual fun open(path: String, options: Map<String, String>, interrupt: OpenInterrupt?): MediaSource

Open with pre-open options: pairs applied between allocation and open, the only moment probesize, fflags and format forcing can act. Keys FFmpeg does not consume are reported through unusedOpenOptions, never silently dropped.

interrupt lets another thread stop this open while it runs, and then stays with the returned source; see OpenInterrupt. The open fails with FFmpegError.Interrupted.


actual fun open(io: MediaByteSource, options: Map<String, String>, interrupt: OpenInterrupt?, url: String?, mimeType: String?, nestedOpener: MediaByteOpener?): MediaSource

Open over caller-supplied bytes: FFmpeg demuxes whatever io reads, with no path involved. The returned source OWNS io and closes it when it closes. Pre-open options and interrupt behave exactly like the path overload's. Blocking, like every open here: call it off the UI thread, and expect io's own read latency to shape the open time.

Three optional parameters say where the bytes come from:

  • url is the address that io reads. The bytes still come from io. FFmpeg uses the address to recognise the format, as it uses a file name, and to resolve the relative addresses inside the media, unless io names its MediaByteSource.location, which they then resolve against, as after a redirect.

  • mimeType is the type the bytes arrived with, such as a server's Content-Type. The probe uses it. An HLS playlist whose url does not end in .m3u8 or .m3u opens only with an HLS type, such as application/vnd.apple.mpegurl.

  • nestedOpener opens the other addresses that the media names, such as the segments and keys of an HLS playlist. Without it, FFmpeg opens those addresses with its own protocols, which have no https.

An HLS stream over https needs url and nestedOpener, and mimeType too when url does not end in .m3u8:

val source = MediaSource.open(
io = playlistBytes,
url = "https://cdn.example/live/index",
mimeType = "application/vnd.apple.mpegurl",
nestedOpener = { address -> if (address.startsWith("https://cdn.example/")) fetch(address) else null },
)

On the web, io is read as FFmpeg asks for its bytes wherever a read may block, which is a Worker, so it can answer with a synchronous range request, and it is closed when the returned source closes. On a page's main thread, where nothing may block, it is read whole into the codec module's memory during the open, up to 512 MB, and closed then. Every source that nestedOpener returns is read whole as soon as the opener returns it, and closed. The opener has to answer at once as well, which on a page means bytes it already holds, and in a Worker can mean a synchronous request.

actual fun open(path: String): MediaSource

Open a local file or URL.

This is a blocking call. Network URLs perform I/O inside the native open, so call it from a background dispatcher (Dispatchers.IO or your media dispatcher). Never call it on the UI thread.


actual fun open(path: String, options: Map<String, String>, interrupt: OpenInterrupt?): MediaSource

Open with pre-open options: pairs applied between allocation and open, the only moment probesize, fflags and format forcing can act. Keys FFmpeg does not consume are reported through unusedOpenOptions, never silently dropped.

interrupt lets another thread stop this open while it runs, and then stays with the returned source; see OpenInterrupt. The open fails with FFmpegError.Interrupted.


actual fun open(io: MediaByteSource, options: Map<String, String>, interrupt: OpenInterrupt?, url: String?, mimeType: String?, nestedOpener: MediaByteOpener?): MediaSource

Open over caller-supplied bytes: FFmpeg demuxes whatever io reads, with no path involved. The returned source OWNS io and closes it when it closes. Pre-open options and interrupt behave exactly like the path overload's. Blocking, like every open here: call it off the UI thread, and expect io's own read latency to shape the open time.

Three optional parameters say where the bytes come from:

  • url is the address that io reads. The bytes still come from io. FFmpeg uses the address to recognise the format, as it uses a file name, and to resolve the relative addresses inside the media, unless io names its MediaByteSource.location, which they then resolve against, as after a redirect.

  • mimeType is the type the bytes arrived with, such as a server's Content-Type. The probe uses it. An HLS playlist whose url does not end in .m3u8 or .m3u opens only with an HLS type, such as application/vnd.apple.mpegurl.

  • nestedOpener opens the other addresses that the media names, such as the segments and keys of an HLS playlist. Without it, FFmpeg opens those addresses with its own protocols, which have no https.

An HLS stream over https needs url and nestedOpener, and mimeType too when url does not end in .m3u8:

val source = MediaSource.open(
io = playlistBytes,
url = "https://cdn.example/live/index",
mimeType = "application/vnd.apple.mpegurl",
nestedOpener = { address -> if (address.startsWith("https://cdn.example/")) fetch(address) else null },
)

On the web, io is read as FFmpeg asks for its bytes wherever a read may block, which is a Worker, so it can answer with a synchronous range request, and it is closed when the returned source closes. On a page's main thread, where nothing may block, it is read whole into the codec module's memory during the open, up to 512 MB, and closed then. Every source that nestedOpener returns is read whole as soon as the opener returns it, and closed. The opener has to answer at once as well, which on a page means bytes it already holds, and in a Worker can mean a synchronous request.

actual fun open(path: String): MediaSource

Open a local file or URL.

This is a blocking call. Network URLs perform I/O inside the native open, so call it from a background dispatcher (Dispatchers.IO or your media dispatcher). Never call it on the UI thread.


actual fun open(path: String, options: Map<String, String>, interrupt: OpenInterrupt?): MediaSource

Open with pre-open options: pairs applied between allocation and open, the only moment probesize, fflags and format forcing can act. Keys FFmpeg does not consume are reported through unusedOpenOptions, never silently dropped.

interrupt lets another thread stop this open while it runs, and then stays with the returned source; see OpenInterrupt. The open fails with FFmpegError.Interrupted.


actual fun open(io: MediaByteSource, options: Map<String, String>, interrupt: OpenInterrupt?, url: String?, mimeType: String?, nestedOpener: MediaByteOpener?): MediaSource

Open over caller-supplied bytes: FFmpeg demuxes whatever io reads, with no path involved. The returned source OWNS io and closes it when it closes. Pre-open options and interrupt behave exactly like the path overload's. Blocking, like every open here: call it off the UI thread, and expect io's own read latency to shape the open time.

Three optional parameters say where the bytes come from:

  • url is the address that io reads. The bytes still come from io. FFmpeg uses the address to recognise the format, as it uses a file name, and to resolve the relative addresses inside the media, unless io names its MediaByteSource.location, which they then resolve against, as after a redirect.

  • mimeType is the type the bytes arrived with, such as a server's Content-Type. The probe uses it. An HLS playlist whose url does not end in .m3u8 or .m3u opens only with an HLS type, such as application/vnd.apple.mpegurl.

  • nestedOpener opens the other addresses that the media names, such as the segments and keys of an HLS playlist. Without it, FFmpeg opens those addresses with its own protocols, which have no https.

An HLS stream over https needs url and nestedOpener, and mimeType too when url does not end in .m3u8:

val source = MediaSource.open(
io = playlistBytes,
url = "https://cdn.example/live/index",
mimeType = "application/vnd.apple.mpegurl",
nestedOpener = { address -> if (address.startsWith("https://cdn.example/")) fetch(address) else null },
)

On the web, io is read as FFmpeg asks for its bytes wherever a read may block, which is a Worker, so it can answer with a synchronous range request, and it is closed when the returned source closes. On a page's main thread, where nothing may block, it is read whole into the codec module's memory during the open, up to 512 MB, and closed then. Every source that nestedOpener returns is read whole as soon as the opener returns it, and closed. The opener has to answer at once as well, which on a page means bytes it already holds, and in a Worker can mean a synchronous request.

actual fun open(path: String): MediaSource

Open a local file or URL.

This is a blocking call. Network URLs perform I/O inside the native open, so call it from a background dispatcher (Dispatchers.IO or your media dispatcher). Never call it on the UI thread.


actual fun open(path: String, options: Map<String, String>, interrupt: OpenInterrupt?): MediaSource

Open with pre-open options: pairs applied between allocation and open, the only moment probesize, fflags and format forcing can act. Keys FFmpeg does not consume are reported through unusedOpenOptions, never silently dropped.

interrupt lets another thread stop this open while it runs, and then stays with the returned source; see OpenInterrupt. The open fails with FFmpegError.Interrupted.


actual fun open(io: MediaByteSource, options: Map<String, String>, interrupt: OpenInterrupt?, url: String?, mimeType: String?, nestedOpener: MediaByteOpener?): MediaSource

Open over caller-supplied bytes: FFmpeg demuxes whatever io reads, with no path involved. The returned source OWNS io and closes it when it closes. Pre-open options and interrupt behave exactly like the path overload's. Blocking, like every open here: call it off the UI thread, and expect io's own read latency to shape the open time.

Three optional parameters say where the bytes come from:

  • url is the address that io reads. The bytes still come from io. FFmpeg uses the address to recognise the format, as it uses a file name, and to resolve the relative addresses inside the media, unless io names its MediaByteSource.location, which they then resolve against, as after a redirect.

  • mimeType is the type the bytes arrived with, such as a server's Content-Type. The probe uses it. An HLS playlist whose url does not end in .m3u8 or .m3u opens only with an HLS type, such as application/vnd.apple.mpegurl.

  • nestedOpener opens the other addresses that the media names, such as the segments and keys of an HLS playlist. Without it, FFmpeg opens those addresses with its own protocols, which have no https.

An HLS stream over https needs url and nestedOpener, and mimeType too when url does not end in .m3u8:

val source = MediaSource.open(
io = playlistBytes,
url = "https://cdn.example/live/index",
mimeType = "application/vnd.apple.mpegurl",
nestedOpener = { address -> if (address.startsWith("https://cdn.example/")) fetch(address) else null },
)

On the web, io is read as FFmpeg asks for its bytes wherever a read may block, which is a Worker, so it can answer with a synchronous range request, and it is closed when the returned source closes. On a page's main thread, where nothing may block, it is read whole into the codec module's memory during the open, up to 512 MB, and closed then. Every source that nestedOpener returns is read whole as soon as the opener returns it, and closed. The opener has to answer at once as well, which on a page means bytes it already holds, and in a Worker can mean a synchronous request.