Сохраните Twilio <Stream>формата 8Khz `mulaw` в файл - PullRequest
0 голосов
/ 31 марта 2020

Есть пара постов, посвященных этому вопросу, но я не смог успешно воспроизвести сохраненный файл. Обычно он воспроизводится с половинной скоростью.

Преобразование 8 кГц мулав в 16 кГц PCM в режиме реального времени

Используя принятый ответ в предыдущем вопросе, я сохранил raw и base64, декодировавший аудио в go:

// Media event
type Media struct {
    Track     string `json:"track"`
    Chunk     string `json:"chunk"`
    Timestamp string `json:"timestamp"`
    Payload   string `json:"payload"`
}

// SaveAudio will upgrade connection to websocket and save the audio to file
func SaveAudio(w http.ResponseWriter, r *http.Request) {
    utility.DebugLogf("SaveAudio")
    c, err := upgrader.Upgrade(w, r, nil)
    if err != nil {
        log.Print("upgrade:", err)
        return
    }

    defer utility.SafeClose(c)
    inBuf := bytes.Buffer{}

    loop := true
    for loop == true {
        _, message, err := c.ReadMessage()
        utility.PanicIfErr(err)
        decMessage := TwilioWSSMessage{}
        err = json.Unmarshal(message, &decMessage)
        utility.PanicIfErr(err)

        switch decMessage.Event {
        case "connected":
            utility.DebugLogf("Connected a %s protocol version:%s", decMessage.Protocol, decMessage.Version)
        case "start":
            utility.DebugLogf("Starting audio stream: %#v", decMessage.Start)
        case "media":
            chunk, err := base64.StdEncoding.DecodeString(decMessage.Media.Payload)
            utility.PanicIfErr(err)
            _, err = inBuf.Write(chunk)
            utility.PanicIfErr(err)
        case "stop":
            utility.DebugLogf("Ending audio stream: %#v", decMessage.Stop)
            loop = false
        default:
            utility.LogWarningf("Unrecognized event type: %s", decMessage.Event)
            loop = false
        }
    }

    saveRaw(&inBuf)
}

func saveRaw(buf *bytes.Buffer) {
    rawOut, err := os.Create("out.ulaw")
    utility.PanicIfErr(err)

    _, err = rawOut.Write(buf.Bytes())
    utility.PanicIfErr(err)
}

Затем я использовал ffmpeg для преобразования из mulaw в значение по умолчанию pcm_s16le:

ffmpeg -f mulaw -ar 8000 -ac 1 -i out.ulaw mulaw_decoded.wav 

Затем увеличил частоту с 8к до 16к и воспроизвел ее с vl c:

ffmpeg -i mulaw_decoded.wav -ar 16000 upsampled.wav && vlc upsampled.wav

Но он играет на половинной скорости.

В конечном итоге я бы хотел сделать все это в ржавчине или go, но я даже не могу получить это работает локально только с ffmpeg.

Заранее спасибо.


Вывод вышеуказанных двух операций ffmpeg в сочетании с предлагаемым ресэмплером sox:

cmd:

ffmpeg -y -loglevel verbose -f mulaw -ar 8000 -ac 1 -bits_per_raw_sample 8 -i testsamples/raw_mulaw_bytes -af aresample=resampler=soxr -ar 16000 upsampled.wav

вывод:

[mulaw @ 0x7fecc0814000] Estimating duration from bitrate, this may be inaccurate
Guessed Channel Layout for Input Stream #0.0 : mono
Input #0, mulaw, from 'testsamples/raw_mulaw_bytes':
  Duration: 00:00:20.74, bitrate: 64 kb/s
    Stream #0:0: Audio: pcm_mulaw, 8000 Hz, mono, s16, 64 kb/s
Stream mapping:
  Stream #0:0 -> #0:0 (pcm_mulaw (native) -> pcm_s16le (native))
Press [q] to stop, [?] for help
[graph_0_in_0_0 @ 0x7fecc0505600] tb:1/8000 samplefmt:s16 samplerate:8000 chlayout:0x4
[Parsed_aresample_0 @ 0x7fecc0505280] ch:1 chl:mono fmt:s16 r:8000Hz -> ch:1 chl:mono fmt:s16 r:16000Hz
Output #0, wav, to 'upsampled.wav':
  Metadata:
    ISFT            : Lavf58.29.100
    Stream #0:0: Audio: pcm_s16le ([1][0][0][0] / 0x0001), 16000 Hz, mono, s16, 256 kb/s
    Metadata:
      encoder         : Lavc58.54.100 pcm_s16le
No more output streams to write to, finishing.
size=     648kB time=00:00:20.74 bitrate= 256.0kbits/s speed=1.55e+03x
video:0kB audio:648kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: 0.011753%
Input file #0 (testsamples/raw_mulaw_bytes):
  Input stream #0:0 (audio): 519 packets read (165920 bytes); 519 frames decoded (165920 samples);
  Total: 519 packets (165920 bytes) demuxed
Output file #0 (upsampled.wav):
  Output stream #0:0 (audio): 200 frames encoded (331840 samples); 200 packets muxed (663680 bytes);
  Total: 200 packets (663680 bytes) muxed
[AVIOContext @ 0x7fecc0433cc0] Statistics: 4 seeks, 6 writeouts
[AVIOContext @ 0x7fecc042a6c0] Statistics: 165920 bytes read, 0 seeks

Звук звучит так же, как и раньше

1 Ответ

1 голос
/ 02 апреля 2020

Я наконец понял это благодаря этому ответу: Эффект замедления при декодировании аудиопотока OPUS

, где он упоминает:

Другая возможная причина «медленное движение» - это более одного потока, декодированного одним и тем же декодером. Но в этом случае вы также получаете искаженное медленное аудио.

, поэтому дорожки для этого вызова inbound и outbound, поэтому в case "media": можно сохранить только одну дорожку:

if decMessage.Media.Track == "outbound" {
  chunk, err := base64.StdEncoding.DecodeString(decMessage.Media.Payload)
  utility.PanicIfErr(err)
  _, err = outboundBuf.Write(chunk)
  utility.PanicIfErr(err)
}

и команды ffmpeg работают как положено

...