简介

输出格式指定了由Output写入的数据的容器格式。Mediabunny 支持许多常用的容器格式,每种格式都有特定的选项。

许多格式还提供数据回调,这是针对输出文件中特定数据区域触发的特殊回调函数。

输出格式属性

所有输出格式都有一组通用的属性可供查询。

// 获取格式的扩展名:
format.fileExtension; // => '.mp4'

// 获取格式的基础 MIME 类型:
format.mimeType; // => 'video/mp4'

// 检查该格式可以包含哪些编解码器:
format.getSupportedCodecs(); // => MediaCodec[]
format.getSupportedVideoCodecs(); // => VideoCodec[]
format.getSupportedAudioCodecs(); // => AudioCodec[]
format.getSupportedSubtitleCodecs(); // => SubtitleCodec[]

// 检查该格式是否支持带有旋转和翻转元数据的视频轨道:
format.supportsVideoTransformationMetadata; // => boolean

请参阅兼容性表以查看哪些编解码器可与哪种输出格式配合使用。

不同格式在可包含的轨道数量和类型上也存在差异。您可以使用以下方法检索此信息:

format.getSupportedTrackCounts(); // => TrackCountLimits

type TrackCountLimits = {
	video: { min: number, max: number },
	audio: { min: number, max: number },
	subtitle: { min: number, max: number },
	total: { min: number, max: number },
};

仅追加写入

某些输出格式配置采用仅追加模式写入。这意味着它们仅向文件末尾添加新数据,而无需回退到之前写入的部分进行覆盖。或者,从形式上讲:任何写入操作的字节偏移量恰好等于此前已写入的字节数。

仅追加格式与StreamTarget结合使用时具有某些有用特性。它们支持与Media Source Extensions配合使用,并允许通过网络轻松流式传输,例如用于文件上传。

MP4

此输出格式用于创建 MP4 文件。

import { Output, Mp4OutputFormat } from 'mediabunny';

const output = new Output({
	format: new Mp4OutputFormat(options),
	// ...
});

以下选项可用:

type IsobmffOutputFormatOptions = {
	fastStart?: false | 'in-memory' | 'reserve' | 'fragmented';
	minimumFragmentDuration?: number;
	metadataFormat?: 'mdir' | 'mdta' | 'udta' | 'auto';

	onFtyp?: (data: Uint8Array, position: number) => unknown;
	onMoov?: (data: Uint8Array, position: number) => unknown;
	onMdat?: (data: Uint8Array, position: number) => unknown;
	onMoof?: (data: Uint8Array, position: number, timestamp: number) => unknown;
};
  • fastStart
    控制文件中元数据的位置。将元数据置于文件开头称为“快速启动”(Fast Start),并提供某些优势:文件更容易在没有范围请求的情况下通过 Web 流式传输,且像 YouTube 这样的网站可以在视频上传时就开始处理它。然而,将元数据置于文件开头可能在写入步骤中需要更多的处理和内存。本库提供完全控制元数据放置的功能,可通过将fastStart设置为以下选项之一来实现:
    • false
      禁用快速启动,将元数据放置在文件末尾。速度最快且占用内存最少。
    • 'in-memory'
      通过将所有媒体块保留在内存中直到文件最终确定,生成带有快速启动的文件。这会产生高质量且紧凑的输出,但代价是最终确定步骤更昂贵且对内存要求更高。

      此选项确保仅追加写入,尽管所有写入操作都在最后批量完成。

    • 'reserve'
      通过在文件开头预留空间来生成带有快速启动的文件,稍后将在此处写入元数据。这需要预先了解文件的预期长度。使用此选项时,您必须为所有轨道设置轨道元数据中的maximumPacketCount字段。
    • 'fragmented'
      生成分片 MP4 (fMP4)文件,通过将样本元数据分组为“片段”(媒体的短节段)并将其均匀分布在文件中,同时将通用元数据放在文件开头。分片文件非常适合流式传输场景,因为每个片段都可以单独播放,而无需了解其他片段。此外,无论文件大小如何增长,它们的创建都保持轻量级,因为它们不需要长时间将媒体保留在内存中。然而,分片文件的广泛性和完整性支持不如常规 MP4 文件,某些播放器也不提供对其的搜索功能。

      此选项确保仅追加写入。

      警告

      此选项需要数据包缓冲。

    • undefined
      默认选项;在使用BufferTarget时行为类似于'in-memory',否则类似于false。
  • minimumFragmentDuration
    仅在 fastStart 为 'fragmented' 时相关。设置片段必须具有的最小持续时间(秒),以便最终确定并写入文件。默认为 1 秒。
  • metadataFormat
    用于写入元数据标签的元数据格式。
    • 'auto'(默认):对于 MP4 表现如 'mdir',对于 QuickTime 表现如 'udta',与 FFmpeg 的默认行为匹配。
    • 'mdir':使用 'mdir' 处理程序格式将标签写入 moov/udta/meta。
    • 'mdta':使用 'mdta' 处理程序格式将标签写入 moov/udta/meta,等同于 FFmpeg 的 use_metadata_tags 标志。这允许使用任意长度的自定义键。
    • 'udta':直接将标签写入 moov/udta。
  • onFtyp
    当输出文件的 ftyp (File Type) box 写入后将被调用。
  • onMoov
    当输出文件的 moov (Movie) box 写入后将被调用。
  • onMdat
    对输出文件的每个最终确定的 mdat (Media Data) box 进行调用。如果不使用 fastStart: 'fragmented',则不建议使用此回调,因为将存在一个单体 mdat box,可能需要大量内存。
  • onMoof
    对输出文件的每个最终确定的 moof (Movie Fragment) box 进行调用。同时传递片段的起始时间戳(秒)。

QuickTime 文件格式 (.mov) ​

此输出格式创建 QuickTime 文件 (.mov)。

import { Output, MovOutputFormat } from 'mediabunny';

const output = new Output({
	format: new MovOutputFormat(options),
	// ...
});

可用的选项与 MP4 使用的 IsobmffOutputFormatOptions 相同。

CMAF ​

此输出格式创建单个通用媒体应用格式 (CMAF) 段 (.m4s)。

import { Output, CmafOutputFormat } from 'mediabunny';

const output = new Output({
	format: new CmafOutputFormat(options),
	initTarget: new BufferTarget(), // 例如
	// ...
});

CMAF 段需要一个单独的初始化段,该段将写入由 OutputOptions.initTarget 指定的目标。

可用的选项与 MP4 使用的 IsobmffOutputFormatOptions 相同,但移除了 fastStart 选项,且 minimumFragmentDuration 默认为 Infinity。

CMAF 主要设计用作 HLS 的段格式。

WebM ​

此输出格式创建 WebM 文件。

import { Output, WebMOutputFormat } from 'mediabunny';

const output = new Output({
	format: new WebMOutputFormat(options),
	// ...
});

提供以下选项:

type MkvOutputFormatOptions = {
	appendOnly?: boolean;
	minimumClusterDuration?: number;

	onEbmlHeader?: (data: Uint8Array, position: number) => void;
	onSegmentHeader?: (data: Uint8Array, position: number) => unknown;
	onCluster?: (data: Uint8Array, position: number, timestamp: number) => unknown;
};
  • appendOnly
    配置输出以追加方式写入数据。这对于在创建过程中实时流式传输输出非常有用。注意,启用时,某些功能(如文件时长或搜索)将被禁用或受到影响,因此如果您希望稍后使用而写入媒体文件,请不要使用此选项。

    此选项确保追加写入。

  • minimumClusterDuration
    设置集群必须具有的最小持续时间(秒),以便最终确定并写入文件。默认为 1 秒。
  • onEbmlHeader
    当输出文件的 EBML header 写入后将被调用。
  • onSegmentHeader
    当 Matroska Segment 元素的头部部分写入后将被调用。头部数据包括 Segment 元素及其内部所有内容,直到(但不包括)第一个 Matroska Cluster。
  • onCluster
    对输出文件的每个最终确定的 Matroska Cluster 进行调用。同时传递集群的起始时间戳(秒)。

Matroska (.mkv) ​

此输出格式创建 Matroska 文件 (.mkv)。

import { Output, MkvOutputFormat } from 'mediabunny';

const output = new Output({
	format: new MkvOutputFormat(options),
	// ...
});

可用的选项与 WebM 使用的 MkvOutputFormatOptions 相同。

Ogg ​

此输出格式创建 Ogg 文件。

import { Output, OggOutputFormat } from 'mediabunny';

const output = new Output({
	format: new OggOutputFormat(options),
	// ...
});

此格式确保追加写入。

提供以下选项:

type OggOutputFormatOptions = {
	maximumPageDuration?: number;
	onPage?: (data: Uint8Array, position: number, source: MediaSource) => unknown;
};
  • maximumPageDuration
    每个 Ogg page 的最大持续时间(秒)。如果添加另一个 packet 会导致 page 超过此持续时间,则提前刷新 page。这对于需要更频繁页面输出的流式传输上下文非常有用。默认情况下,仅在 page 超过一定大小时才刷新。
  • onPage
    对输出文件的每个最终确定的 Ogg page 进行调用。同时传递 backing page track (logical bitstream) 的 媒体源。

MP3 ​

此输出格式创建 MP3 文件。

import { Output, Mp3OutputFormat } from 'mediabunny';	

const output = new Output({
	format: new Mp3OutputFormat(options),
	// ...
});

以下选项可用:

type Mp3OutputFormatOptions = {
	xingHeader?: boolean;
	onXingFrame?: (data: Uint8Array, position: number) => unknown;
};
  • xingHeader
    控制是否在 MP3 文件开头写入包含附加元数据及索引的 Xing header。默认为 true。

    设置为 false 时,此选项可确保仅追加写入。

  • onXingFrame
    当 Xing 元数据帧完成时将被调用,这发生在写入过程的末尾。仅当 xingHeader 未设置为 false 时,此回调才会触发。

大多数浏览器不支持编码 MP3。请使用官方的 @mediabunny/mp3-encoder 包来为编码器提供多态支持(polyfill)。

WAVE ​

此输出格式用于创建 WAVE (.wav) 文件。

import { Output, WavOutputFormat } from 'mediabunny';	

const output = new Output({
	format: new WavOutputFormat(options),
	// ...
});

以下选项可用:

type WavOutputFormatOptions = {
	large?: boolean;
	metadataFormat?: 'info' | 'id3';
	onHeader?: (data: Uint8Array, position: number) => unknown;
};
  • large
    启用后,将写入 RF64 文件,允许文件大小超过 4 GiB,而常规 WAVE 文件无法做到这一点。
  • metadataFormat
    用于写入元数据标签的元数据格式。
    • 'info'(默认):将元数据写入 RIFF INFO LIST chunk,这是 WAVE 中包含元数据标签的默认方式。仅允许写入有限的一组标签。
    • 'id3':将元数据写入 ID3 chunk。非默认设置,但在实践中被许多标签工具使用。允许写入更大且更丰富的标签集。
  • onHeader
    文件头写入完成后将被调用。文件头由 RIFF 头、format chunk 以及 data chunk 的开头(大小为 0 的占位符)组成。

ADTS ​

此输出格式用于创建 ADTS (.aac) 文件。

import { Output, AdtsOutputFormat } from 'mediabunny';	

const output = new Output({
	format: new AdtsOutputFormat(options),
	// ...
});

此格式可确保仅追加写入。

以下选项可用:

type AdtsOutputFormatOptions = {
	onFrame?: (data: Uint8Array, position: number) => unknown;
};
  • onFrame
    每写入一个 ADTS 帧时将被调用。

FLAC ​

此输出格式用于创建 FLAC (.flac) 文件。

import { Output, FlacOutputFormat } from 'mediabunny';

const output = new Output({
	format: new FlacOutputFormat(options),
	// ...
});

以下选项可用:

type FlacOutputFormatOptions = {
	appendOnly?: boolean;

	onFrame?: (data: Uint8Array, position: number) => unknown;
};
  • appendOnly
    配置输出仅在末尾追加新数据,适用于在创建文件的同时进行直播流式传输。启用后,STREAMINFO block 将不会以准确的 min/max block size、frame size 或总样本数进行最终确定,因此如果您希望写入供后续使用的干净文件,请不要使用此选项。

    此选项可确保仅追加写入。

  • onFrame
    每写入一个 FLAC 帧时将被调用。

MPEG-TS ​

此输出格式用于创建 MPEG Transport Stream (.ts) 文件。

import { Output, MpegTsOutputFormat } from 'mediabunny';

const output = new Output({
	format: new MpegTsOutputFormat(options),
	// ...
});

此格式可确保仅追加写入。

以下选项可用:

type MpegTsOutputFormatOptions = {
	onPacket?: (data: Uint8Array, position: number) => unknown;
};
  • onPacket
    每写入一个 188 字节的 Transport Stream 数据包时将被调用。

HLS ​

此输出格式用于创建与 HTTP Live Streaming (HLS) 协议兼容的媒体文件。HLS 媒体由一组 .m3u8 播放列表文件和媒体片段文件表示,意味着此格式会写入多个文件,需要使用 带路径的 Output(pathed Output)。

此输出格式会创建以下文件:

  • 主播放列表 .m3u8 文件,包含可用播放列表的列表。主播放列表始终会被发出,并写入根路径。
  • 每个播放列表对应一个 .m3u8 文件,每个文件包含媒体片段列表。
  • 许多媒体片段,包含实际的媒体数据。

若要发出使用 #EXT-X-PROGRAM-DATE-TIME 标签将片段时间戳映射到现实时间的媒体播放列表,请将所有输出轨道的 BaseTrackMetadata.isRelativeToUnixEpoch 设置为 true。

import { Output, PathedTarget, MpegTsOutputFormat } from 'mediabunny';

const output = new Output({
	format: new HlsOutputFormat(options),
	target: new PathedTarget('master.m3u8', ({ path }) => {
		// 返回一个目标
	}),
});

此格式可为主播放列表和媒体播放列表确保仅追加写入;对于媒体片段,则取决于媒体片段的格式。

以下选项可用:

export type HlsOutputFormatOptions = {
	segmentFormat: OutputFormat | OutputFormat[];

	targetDuration?: number;
	singleFilePerPlaylist?: boolean;
	live?: boolean;
	maxLiveSegmentCount?: number;
	getPlaylistPath?: (info: HlsOutputPlaylistInfo) => MaybePromise<FilePath>;
	getSegmentPath?: (info: HlsOutputSegmentInfo) => MaybePromise<FilePath>;
	getInitPath?: (info: HlsOutputPlaylistInfo) => MaybePromise<FilePath>;

	onMaster?: (content: string) => unknown;
	onPlaylist?: (content: string, info: HlsOutputPlaylistInfo) => unknown;
	onSegment?: (target: Target, info: HlsOutputSegmentInfo) => unknown;
	onInit?: (target: Target, info: HlsOutputPlaylistInfo) => unknown;
};
  • segmentFormat
    必填。指定每个媒体段(media segment)的文件格式。并非所有播放器都支持所有格式;建议优先使用最常用的格式:MpegTsOutputFormat、CmafOutputFormat、AdtsOutputFormat和Mp3OutputFormat。

    当指定格式数组时,对于每个播放列表(playlist),会选择第一个能够包含该播放列表所有轨道的格式。这使得您例如可以将音频打包为.aac文件,将视频打包为.ts文件。

  • targetDuration
    指定每个媒体段的目标(最大)持续时间(秒),默认为2秒。

    Mediabunny 会尝试不生成超过目标持续时间的媒体段,但如果提供的关键帧间隔长于目标持续时间,则被迫生成更长的段。因此,请确保至少每targetDuration秒编码一个关键帧以保证段长度,这可以通过VideoEncodingConfig.keyFrameInterval进行控制。

  • singleFilePerPlaylist
    是否将播放列表的所有媒体段捆绑到单个文件中。然后通过范围请求提取单独的段。

  • live
    如果为true,复用器将处于“直播模式”,随着新段的创建持续发出更新的播放列表。主播放列表将在所有播放列表至少被发出一次后立即发出,并且每次有段最终确定时都会继续发出,以进一步细化BANDWIDTH属性的准确性。

    当为false(默认值)时,所有播放列表仅在输出最终确定时发出一次。

  • maxLiveSegmentCount
    在直播模式下,此参数控制每个播放列表中包含的最大段数。默认为Infinity,意味着播放列表的大小会持续增长。

  • getPlaylistPath
    返回给定媒体播放列表的文件路径。如果返回的路径是相对的,则相对于根路径。

    默认为'playlist-{n}.m3u8',其中n是主播放列表中媒体播放列表的基于1的索引。

  • getSegmentPath
    返回给定媒体段的文件路径。如果返回的路径是相对的,则相对于包含它的播放列表的路径。

    默认为'segment-{n}-{k}{ext}',其中n是主播放列表中包含媒体播放列表的基于1的索引,k是该播放列表中段的基于1的索引,ext是段格式的文件扩展名(包括前导点)。

    如果singleFilePerPlaylist为true,则默认为'segments-{n}{ext}'。

  • getInitPath
    返回给定媒体初始化段(init segment)的文件路径。如果返回的路径是相对的,则相对于包含它的播放列表的路径。

    仅对需要初始化文件的段格式(如CmafOutputFormat)必要。

    默认为'init-{n}{ext}',其中n是主播放列表中包含媒体播放列表的基于1的索引,ext是段格式的文件扩展名(包括前导点)。

  • onMaster
    每当写入主播放列表时调用。

  • onPlaylist
    每当写入媒体播放列表时调用。

  • onSegment
    每当媒体段完全写入后调用。在单文件模式下,此函数仅在播放列表最终确定时调用一次。

  • onInit
    在媒体播放列表初始化时调用,在任何段写入之前。在单文件模式下,此函数永远不会被调用。