dzmdd's picture
Upload folder using huggingface_hub (part 2)
bc50ea0 verified
Raw History Blame Contribute Delete
3.62 kB
"""Exact MiniMax H3 picture/audio timeline helpers.
H3 picture runs live on a 24 fps clock while generated audio latents live on
a 40 Hz clock. A decoded audio stream can consequently land a few
milliseconds either side of its exact frame-derived duration. Small grid
mismatches are time-conformed here instead of being repaired with silence.
"""
from __future__ import annotations
from fractions import Fraction
import logging
import torch
try:
import torchaudio
except ImportError:
torchaudio = None
_LOG = logging.getLogger("minimax_h3_context_loop.av_timing")
# Private AUDIO mapping fields passed only between Loop Trim and Segment Save.
# Keeping this transport inside the existing AUDIO value avoids another public
# socket and another copy of the same decoded stream in user workflows.
AUDIO_WITH_OVERLAP_WAVEFORM_KEY = "_h3_audio_with_overlap_waveform"
AUDIO_WITH_OVERLAP_FRAMES_KEY = "_h3_audio_with_overlap_frames"
AUDIO_TRIM_FRAMES_KEY = "_h3_audio_trim_frames"
def sample_boundary_from_seconds(seconds: float, sample_rate: int) -> int:
"""Return the nearest PCM sample on one absolute time boundary."""
return int(round(float(seconds) * int(sample_rate)))
def sample_boundary_from_frames(
frame_position: int, sample_rate: int, fps: int = 24) -> int:
"""Return the nearest PCM sample on one absolute video-frame boundary."""
return int(round(int(frame_position) / float(fps) * int(sample_rate)))
def conform_waveform_length(
waveform, samples: int, label: str,
max_fractional_change: float = 0.005):
"""Time-conform a small decoder/grid mismatch to an exact sample span.
A larger discrepancy is likely incorrect wiring or timing metadata and is
rejected instead of being hidden by a large resample.
"""
target = int(samples)
current = int(waveform.shape[-1])
if current == target:
return waveform
if current <= 0 or target <= 0:
raise ValueError(
"%s has an invalid audio sample length %d -> %d." %
(label, current, target))
fractional_change = abs(target - current) / float(target)
if fractional_change > float(max_fractional_change):
raise ValueError(
"%s differs from its exact frame timeline by %.3f%% "
"(%d -> %d samples), too large for H3 audio time-conformance." %
(label, fractional_change * 100.0, current, target))
ratio = Fraction(target, current).limit_denominator(10000)
if torchaudio is not None:
conformed = torchaudio.functional.resample(
waveform, int(ratio.denominator), int(ratio.numerator))
else:
shape = tuple(waveform.shape)
conformed = torch.nn.functional.interpolate(
waveform.reshape(-1, 1, current),
size=target,
mode="linear",
align_corners=False,
).reshape(*shape[:-1], target)
# A rational approximation or resampler backend may miss by one sample.
# Correct the residual by interpolation so silence is never introduced.
if int(conformed.shape[-1]) != target:
shape = tuple(conformed.shape)
conformed = torch.nn.functional.interpolate(
conformed.reshape(-1, 1, int(conformed.shape[-1])),
size=target,
mode="linear",
align_corners=False,
).reshape(*shape[:-1], target)
_LOG.info(
"%s time-conformed %d -> %d audio samples (%+.4f%%) to match "
"the exact video timeline",
label, current, target,
(target - current) / float(current) * 100.0)
return conformed