Skip to content

Media quality guide

Audio Sample Rate, Channel, and Clipping Review: Separate Container Facts from Signal Findings

Inspect an audio artifact’s sample rate, channel contract, and bounded clipping observations without turning stream metadata into a broad quality score.

An audio file can report a plausible sample rate and channel count while still containing a clipped region, a silent channel, or a derivative whose stream contract changed. Start with facts that can be reproduced: what the container and decoding software report, what samples were inspected, and which decisions remain outside this check. This is static editorial guidance, not a decoding service or upload service. The review method is not a loudness score or a claim that an audio artifact is good.

Updated

On this page

Write the audio contract before opening samples

The source dates shown in this guide identify documentation checks on 22 October 2026, not original publication dates. Follow each citation for the documentation edition being discussed.

Record the artifact reference, digest or controlled identifier, container, codec, duration, sample rate, channel count, channel layout, sample format, and whether the object is an original or a derivative. A channel count is not the same as a channel layout: two channels may be left and right, dual mono, or an application-specific pair. Treat an unknown layout as unknown instead of guessing from the count.

The python-soundfile, (opens in a new tab) documentation describes a SoundFile as having a sample rate, data format, and number of channels, and its frame index represents one time-step containing one sample per channel. PyAV exposes analogous AudioFrame properties such as sample_rate, layout, samples, and format PyAV, (opens in a new tab). These are observations about a decoded representation, not evidence of recording intent or listening quality.

Write the audio contract before opening samples (table)
Contract itemRecord before signal reviewOpen question
ArtifactControlled identifier, digest, and original or derivative stateIs this the exact object under review?
RateDeclared sample rate and unitDoes decoding software expose the same rate?
ChannelsCount and named layout, or unknownIs two-channel content stereo or dual mono?
SamplesFormat and inspected frame windowWhich threshold representation applies?
TimingFrame timestamps and samples per channelAre discontinuities or rate changes visible?
DispositionIssue class, evidence reference, and owner decisionWho decides whether a derivative is allowed?

Compare metadata with decoded frame observations

Metadata is a declaration to compare, not an independent proof. For a bounded review, collect a small summary per decoded audio frame: frame index, timestamp if present, sample rate, layout, sample count per channel, and a stable issue class. FFmpeg’s ashowinfo reports per-frame timestamps, sample format, channel layout, rate, and samples per channel FFmpeg, (opens in a new tab).

Selected stream fields

Compare metadata with decoded frame observations code example, Plain text
ffprobe -v error -select_streams a:0 \
  -show_entries stream=index,codec_name,sample_rate,channels,channel_layout,sample_fmt,duration \
  -of json MEDIA_REFERENCE

The FFmpeg, (opens in a new tab) documentation supports selecting audio streams, stream fields, and machine-readable output. Keep MEDIA_REFERENCE as a controlled identifier in a report. Do not include a private path, a recording title, tags, or raw packet data in a public diagnostic.

Synthetic decoded summary

Compare metadata with decoded frame observations code example, JSON
{
  "declared": {"sample_rate_hz": 48000, "channels": 2, "layout": "stereo", "sample_format": "fltp"},
  "decoded_frames": [
    {"index": 0, "sample_rate_hz": 48000, "channels": 2, "samples_per_channel": 1024},
    {"index": 1, "sample_rate_hz": 48000, "channels": 2, "samples_per_channel": 1024}
  ]
}

The values are invented for the worksheet. A mismatch such as two declared channels and one decoded channel is a stream-contract finding. It does not explain why the change occurred or whether a listener would prefer one representation. Record the first and last affected frame, not the raw samples.

Define clipping as an observation with a policy

Clipping is easiest to misuse when it is turned into a universal threshold. First document the decoded sample representation and the policy. For a synthetic normalized float fixture, one local policy might count a sample at or beyond full scale as a potential clipped sample.

Bounded synthetic sample check

Define clipping as an observation with a policy code example, Python
from collections.abc import Iterable

def clipping_summary(samples: Iterable[float], limit: float = 1.0, max_samples: int = 100_000):
    inspected = 0
    clipped = 0
    peak = 0.0
    limited = False
    for value in samples:
        if inspected >= max_samples:
            limited = True
            break
        magnitude = abs(value)
        inspected += 1
        clipped += magnitude >= limit
        peak = max(peak, magnitude)
    return {"sample_count": inspected, "potential_clipped_samples": clipped, "absolute_peak": peak, "sample_limit_reached": limited}

synthetic_channel = [0.10, -0.35, 0.99, 1.0, -1.02]
print(clipping_summary(synthetic_channel))

This function is deliberately bounded by max_samples and does not log values. The synthetic result would report two potential clipped samples under this policy. On real data, define whether the threshold is inclusive or exclusive, whether the check is per channel, and how floating-point rounding is handled. An encoded integer stream and a normalized float stream need an explicit representation contract before their thresholds are compared.

FFmpeg’s volumedetect can report mean volume, maximum volume per sample, and a histogram. Its documentation also states that the filter works on 16-bit signed integer samples and converts other input as needed FFmpeg, (opens in a new tab). Use that result as a diagnostic in the filter’s representation, not as a complete clipping count or a listening judgment. If per-channel counts are needed, decode into a bounded analysis buffer and report only counts, positions, and policy identifiers.

Use a worksheet and a disposition table

Record one row per check: artifact reference, stream index, declared rate, observed rate set, declared channel layout, observed layout set, sample format, inspected frame range, peak policy, potential clipping count, issue class, evidence reference, owner decision, and unresolved questions.

Use a worksheet and a disposition table (table)
ObservationSafe interpretationNext action
Declared rate is missingThe stream contract is incompleteRequest a source declaration or classify rate as unknown
Decoded frame rate changesA representation change or decoding-software finding is visiblePreserve frame indexes and investigate the derivative chain
Channel count and layout disagreeThe channel contract is ambiguousAsk the producer to state layout or hold the artifact
One channel has zero energy in the windowThe selected window has no nonzero samples thereInspect another approved window; do not call the whole track silent
Potential clipped samples are countedThe chosen representation crossed the local limitPreserve policy, sample count, and frame range; do not infer cause
No potential clipping in the windowNo crossing was observed under this policy and windowKeep the window and policy; do not generalize to all playback
All selected checks passThe selected stream checks have evidenceContinue provenance, privacy, rights, and accuracy review

Keep “not inspected,” “not available,” and “not observed under this policy” distinct. A short window can miss a transient event, and a decoding-software summary cannot answer whether content is intelligible or pleasant to hear.

Keep diagnostics safe and the next step qualified

The public report can contain a controlled artifact identifier, stream index, frame range, stable issue class, numeric counts, and tool versions. It should not contain raw samples, private paths, recording names, voice labels, or unbounded decoding errors. If a source must be revisited, retain the evidence reference and owner-approved handling boundary rather than copying the audio into a worksheet.

Pair this check with the data provenance log and export guidance. Those resources own source, rights, processing, and broader export questions; this guide owns sample rate, channel, and bounded signal observations.

After the owner has a supported non-health scope, authority to describe the artifact, and a metadata or synthetic review packet, the qualified appraisal request path may be a next preparation step. It does not validate sample rate, accept audio, produce a quote, match a buyer, issue a legal opinion, or grant a license. Keep raw recordings outside this guide and within the owner-approved handling boundary.

Takeaways

  • Record sample rate, channels, layout, and sample format as separate contract fields.
  • Compare declarations with bounded decoded-frame observations instead of treating metadata as proof.
  • Define clipping representation, threshold, window, and channel policy before counting potential crossings.
  • Use stable issue classes and counts; keep raw samples and private labels out of shared diagnostics.
  • Treat a clean technical check as one input to later provenance, privacy, rights, and accuracy review.

Sources

  1. FFmpeg: ffprobe Documentation (opens in a new tab)
  2. FFmpeg: FFmpeg Filters Documentation (opens in a new tab)
  3. PyAV: Audio API (opens in a new tab)
  4. python-soundfile: python-soundfile Documentation (opens in a new tab)

Use the appraisal path after the source and bounded audio review packet are organized.

It does not validate sample rate, accept audio, create a quote, match a buyer, or grant a license.