[Model][Frontend] MiniMax-H3: Add opt-in planar video response encoding (#6288)
Signed-off-by: MosCloud <bwzhang1991@163.com> Co-authored-by: Hongsheng Liu <liuhongsheng4@huawei.com>
This commit is contained in:
1 parent
3d34b8b977
commit
4882a36c41
9 files changed
+1077
-23
No files matched your search
@@ -5,6 +5,7 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import io
|
||||
from collections.abc import Iterable
|
||||
from fractions import Fraction
|
||||
from typing import Any, cast
|
||||
|
||||
@@ -200,3 +201,70 @@ def mux_video_audio_bytes(
|
||||
|
||||
container.close()
|
||||
return buf.getvalue()
|
||||
|
||||
|
||||
def mux_av_video_audio_bytes(
|
||||
video_frames: Iterable[av.VideoFrame],
|
||||
width: int,
|
||||
height: int,
|
||||
audio_waveform: np.ndarray | None = None,
|
||||
*,
|
||||
fps: float = 25.0,
|
||||
audio_sample_rate: int = 44100,
|
||||
video_codec: str = "h264",
|
||||
audio_codec: str = "aac",
|
||||
crf: str = "18",
|
||||
video_codec_options: dict[str, str] | None = None,
|
||||
) -> bytes:
|
||||
"""Mux preconstructed video frames and optional audio into MP4 bytes."""
|
||||
buf = io.BytesIO()
|
||||
with cast(Any, av.open(buf, mode="w", format="mp4")) as container:
|
||||
v_stream = cast(
|
||||
av.VideoStream,
|
||||
container.add_stream(video_codec, rate=Fraction(fps).limit_denominator(10000)),
|
||||
)
|
||||
v_stream.width = width
|
||||
v_stream.height = height
|
||||
v_stream.pix_fmt = "yuv420p"
|
||||
|
||||
options: dict[str, object] = {"crf": str(crf)}
|
||||
if video_codec_options:
|
||||
options.update(video_codec_options)
|
||||
v_stream.options = options
|
||||
|
||||
a_stream: av.AudioStream | None = None
|
||||
samples: np.ndarray | None = None
|
||||
layout: str | None = None
|
||||
if audio_waveform is not None:
|
||||
samples = audio_waveform.astype(np.float32)
|
||||
if samples.ndim == 1:
|
||||
samples = samples.reshape(1, -1)
|
||||
elif samples.ndim == 2 and samples.shape[0] > samples.shape[1]:
|
||||
samples = np.ascontiguousarray(samples.T)
|
||||
num_channels = samples.shape[0]
|
||||
layout = "stereo" if num_channels >= 2 else "mono"
|
||||
a_stream = cast(av.AudioStream, container.add_stream(audio_codec, rate=audio_sample_rate))
|
||||
a_stream.layout = layout
|
||||
|
||||
for frame in video_frames:
|
||||
for packet in v_stream.encode(frame):
|
||||
container.mux(packet)
|
||||
for packet in v_stream.encode():
|
||||
container.mux(packet)
|
||||
|
||||
if a_stream is not None and audio_waveform is not None:
|
||||
if samples is None or layout is None:
|
||||
raise ValueError("Audio samples were not prepared for muxing.")
|
||||
audio_frame = av.AudioFrame.from_ndarray(samples, format="fltp", layout=layout)
|
||||
audio_frame.sample_rate = audio_sample_rate
|
||||
# AAC has a one-frame encoder delay. Mark the input waveform as
|
||||
# starting at t=0 so the MP4 muxer writes the corresponding negative
|
||||
# priming timestamp instead of exposing the delay as leading silence.
|
||||
audio_frame.pts = 0
|
||||
audio_frame.time_base = Fraction(1, audio_sample_rate)
|
||||
for packet in a_stream.encode(audio_frame):
|
||||
container.mux(packet)
|
||||
for packet in a_stream.encode():
|
||||
container.mux(packet)
|
||||
|
||||
return buf.getvalue()
|
||||
Reference in new issue
Block a user