¿Cómo convertir sonido estéreo a mono con FFmpeg?

4 minutos de lectura

Uso la biblioteca FFmpeg para un proyecto personal y necesito ayuda sobre una cosa. Tengo un archivo de música en sonido estéreo y quiero convertir este sonido estéreo en sonido mono. ¿Es posible con esta biblioteca? ¿Hay una función interna para hacer este trabajo? Mi proyecto está en C/C++.

Busqué en la documentación de Doxygen en el sitio web de FFmpeg y en este foro, pero no encontré nada interesante.

Gracias por leer !

  • Como recuerdo, no hay ninguna función, pero puede convertirla fácilmente usted mismo calculando ambos flujos juntos.

    – usuario1810087

    14/09/2016 a las 10:13

  • ¿Tiene algún fragmento de código para dar como ejemplo?

    – Meugiwara

    14/09/2016 a las 11:11

Puedes simplemente usar ffmpeg. El comando directo está presente para el propósito-

ffmpeg -i stereo.flac -ac 1 mono.flac

Convertiría su archivo estéreo en un canal mono. Para más detalles, puede consultar esta página-

https://trac.ffmpeg.org/wiki/Manipulación de canales de audio

  • Gracias, me ayudó mucho! Por cierto, si alguien más necesita convertir la mayor parte de los archivos seguidos, como hice yo: find . -name '*.mp4' -exec ./convert.sh {} \;

    – Marco Arruda

    10 dic 2019 a las 22:44


  • Entonces, dentro de la convert.sh expediente:

    – Marco Arruda

    10 dic 2019 a las 22:45

  • ffmpeg -i $1 -ac 1 $1.mono.mp4

    – Marco Arruda

    10 dic 2019 a las 22:45

  • @MarcoArruda Puedes saltarte el convert.sh archivo invocando ffmpeg directamente con: find . -name '*.mp4' -exec ffmpeg -i '{}' -ac 1 '{}.mono.mp4' \;

    – joshtch

    4 de marzo de 2021 a las 0:12


  • Tenga en cuenta que -ac 1 voluntad mezclar ambos canales estéreo a uno solo mono, lo que podría no ser lo que desea, especialmente si es solo “una fuente mono grabada erróneamente en estéreo”. En ese caso, tira uno de los canales así: ffmpeg -i INPUT -filter_complex '[0:a]channelsplit=channel_layout=stereo:channels=FL[left]' -map '[left]' OUTPUT (reemplazar INPUT & OUTPUT por supuesto). Esto seleccionará el canal izquierdo, si quiere el derecho, use FR y [right] en cambio.

    – scy

    26 de marzo a las 9:21

Avatar de usuario de Steve M
steve m

Usar swr_convert de libswresample para convertir entre formatos. Algo como:

#include "libswresample/swresample.h"

au_convert_ctx = swr_alloc();

out_channel_layout = AV_CH_LAYOUT_MONO;
out_sample_fmt = AV_SAMPLE_FMT_S16;
out_sample_rate = 44100;
out_channels = av_get_channel_layout_nb_channels(out_channel_layout);

in_sample_fmt = pCodecCtx->sample_fmt;
in_channel_layout=av_get_default_channel_layout(pCodecCtx->channels);

au_convert_ctx=swr_alloc_set_opts(au_convert_ctx,out_channel_layout, out_sample_fmt, out_sample_rate,
            in_channel_layout, in_sample_fmt, pCodecCtx->sample_rate, 0, NULL);
swr_init(au_convert_ctx);
//Generate your frame of original audio, then use swr_convert to convert to mono,
//converted number of samples will now be in out_buffer.
int converted = swr_convert(au_convert_ctx, &out_buffer, MAX_AUDIO_FRAME_SIZE, (const uint8_t **)&pFrame->data , pFrame->nb_samples);
//...
swr_free(&au_convert_ctx);

para empezar Esto convertirá el formato original a 44100 kHz mono. También podrías usar pCodecCtx->sample_rate como la frecuencia de muestreo de salida también.

Es la solución más flexible y fácil.

avatar de usuario de user1810087
usuario1810087

Como mencioné en el comentario, podría volver a muestrearlo usted mismo. Depende de lo que ya tengas y del formato que utilices. No puedo darle un código que funcione instantáneamente, pero le daré un ejemplo (mezcla de código pseudo/real).

Después de codificar el cuadro y haber hecho las cosas que tiene que hacer, su búfer de datos se llenará con el audio. Ahora depende de cómo sea tu formato (ver aquí) y cuántos canales tiene. Supongamos que está firmado en estéreo de 16 bits, entonces su búfer se vería así:

+-----+-----+-----+-----+-----+
| LS1 | RS1 | LS2 | RS2 | ... |
+-----+-----+-----+-----+-----+
// LS = LEFT SAMPLE 16 Bit
// RS = RIGHT SAMPLE 16 Bit

Ahora itere a través del búfer y calcule la muestra izquierda y derecha juntas.

for(int i=0; i<sample_size; i+=2) {
    auto r = (static_cast<int32_t>(buffer[i]) + buffer[i+1]) / 2;
    buffer[i] = buffer[i+1] = r;
}

  • esto simplemente no es una buena estrategia, los números en una señal de audio no son solo números, representan una señal que involucra el cambio en esos números más que esos números en sí mismos … como si tuviera una onda sinusoidal donde izquierda y derecha estuviera fuera de fase 180 grados, simplemente no tendría señal en la mezcla mono.

    – Jugador Grady

    1 de julio a las 15:52


¿Ha sido útil esta solución?