最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Go語言調用ffmpeg-api實現(xiàn)音頻重采樣

 更新時間:2022年12月07日 09:25:02   作者:劍客阿良_ALiang  
最近對golang處理音視頻很感興趣,對golang音視頻常用庫goav進行了一番研究。自己寫了一個wav轉采樣率的功能。給大家分享一下,中間遇到了不少坑,解決的過程中還是蠻有意思的,希望大家能喜歡

前言

最近對golang處理音視頻很感興趣,對golang音視頻常用庫goav進行了一番研究。自己寫了一個wav轉采樣率的功能。給大家分享一下,中間遇到了不少坑,解決的過程中還是蠻有意思的。

環(huán)境部署

代碼運行在Ubuntu環(huán)境上,需要使用到goav,goav是對ffmpeg源碼的golang封裝。

goav地址:https://github.com/giorgisio/goav

goav安裝如下

sudo apt-get -y install autoconf automake build-essential libass-dev libfreetype6-dev libsdl1.2-dev libtheora-dev libtool libva-dev libvdpau-dev libvorbis-dev libxcb1-dev libxcb-shm0-dev libxcb-xfixes0-dev pkg-config texi2html zlib1g-dev
 
sudo apt install -y libavdevice-dev libavfilter-dev libswscale-dev libavcodec-dev libavformat-dev libswresample-dev libavutil-dev
 
sudo apt-get install yasm
 
export FFMPEG_ROOT=$HOME/ffmpeg
export CGO_LDFLAGS="-L$FFMPEG_ROOT/lib/ -lavcodec -lavformat -lavutil -lswscale -lswresample -lavdevice -lavfilter"
export CGO_CFLAGS="-I$FFMPEG_ROOT/include"
export LD_LIBRARY_PATH=$HOME/ffmpeg/lib
``` 
 
``` 
go get github.com/xueqing/goav

代碼

先看代碼

package main
 
//#include<stdlib.h>
import "C"
import (
    "flag"
    "fmt"
    "github.com/google/logger"
    "github.com/xueqing/ffmpeg-demo/logutil"
    "github.com/xueqing/goav/libswresample"
    "github.com/youpy/go-wav"
    "io"
    "os"
    "reflect"
    "unsafe"
)
 
func main() {
    var (
        inputUrl      string = "./data/1.wav"
        inNumChannels int64  = 1
        inSampleRate  int    = 16000
        //inBitsPerSample  uint16                    = 16
        outNumChannels   int64                     = 1
        outSampleRate    int                       = 48000
        outBitsPerSample uint16                    = 16
        swr              *libswresample.SwrContext = libswresample.SwrAlloc()
    )
    flag.Parse()
    logutil.Init(true, false, "resample.log")
    defer logutil.Close()
    swr.SwrAllocSetOpts(outNumChannels,
        libswresample.AvSampleFormat(1),
        outSampleRate,
        inNumChannels,
        libswresample.AvSampleFormat(1),
        inSampleRate,
        0,
        0)
    swr.SwrInit()
    defer swr.SwrClose()
 
    _inputFile, err := os.Open(inputUrl)
    if err != nil {
        logger.Errorf("open input file error(%v)", err)
        return
    }
    defer _inputFile.Close()
    _reader := wav.NewReader(_inputFile)
    format, err := _reader.Format()
    if err != nil {
        logger.Errorf("input file format error(%v)", err)
        return
    }
    fmt.Printf("input file format info -> AudioFormat:%v,NumChannels:%v,SampleRate:%v,ByteRate:%v,BlockAlign:%v,BitsPerSample:%v", int(format.AudioFormat), format.NumChannels, format.SampleRate, format.ByteRate, format.BlockAlign, format.BitsPerSample)
 
    _tempFile, err := os.CreateTemp("", "*.wav")
    if err != nil {
        logger.Errorf("create temp file error(%v)", err)
        return
    }
    logger.Infof("Create tempFile %v", _tempFile.Name())
    defer func() {
        _tempFile.Close()
    }()
    _samples := []wav.Sample{}
    n := 4096
    for {
        spls, err := _reader.ReadSamples(uint32(n))
        if err == io.EOF {
            break
        }
        _samples = append(_samples, spls...)
    }
    _result := ResampleByFFmpegApi2(swr, _samples)
    _writer := wav.NewWriter(_tempFile, uint32(len(_result)), uint16(outNumChannels), uint32(outSampleRate), outBitsPerSample)
 
    err4 := _writer.WriteSamples(_result)
    if err4 != nil {
        logger.Errorf("write file error(%v)", err4)
        err = err4
        return
    }
}
 
func ResampleByFFmpegApi2(swr *libswresample.SwrContext, samples []wav.Sample) []wav.Sample {
    var (
        _inArr  **uint8
        _outArr **uint8
        _inptr  []uint16
        _outptr []uint16
    )
    _inArr = (**uint8)(C.malloc(C.sizeof_int))
    defer C.free(unsafe.Pointer(_inArr))
    _inptr = make([]uint16, len(samples))
    _outArr = (**uint8)(C.malloc(C.sizeof_int))
    defer C.free(unsafe.Pointer(_outArr))
    _outptr = make([]uint16, len(samples)*3)
    //fmt.Println(unsafe.Sizeof(uint16(0)))
    for i, v := range samples {
        _inptr[i] = uint16(v.Values[0])
    }
    *_inArr = (*uint8)(unsafe.Pointer((*reflect.SliceHeader)(unsafe.Pointer(&_inptr)).Data))
    *_outArr = (*uint8)(unsafe.Pointer((*reflect.SliceHeader)(unsafe.Pointer(&_outptr)).Data))
    ret := swr.SwrConvert(_outArr, len(samples)*3, _inArr, len(samples))
    if ret > 0 {
        fmt.Println(ret)
    }
    _result := make([]wav.Sample, ret)
 
    for i := 0; i < ret; i++ {
        _result[i] = wav.Sample{[2]int{int(_outptr[i]), 0}}
    }
    return _result
}

代碼說明:

1、代碼不是個工具方法,如果看懂邏輯的話,可以自行修改成工具方法。

2、里面會用到ffmpeg里面swresample庫,對音頻數(shù)據(jù)進行沖采樣。

3、可以細看一下,如果你想作實時處理也是可以改的。

4、其中SwrAllocSetOpts方法中有個參數(shù)libswresample.AvSampleFormat(1),為什么取1,這里主要是選擇采樣表示方式的枚舉,參考底層源碼枚舉,我發(fā)在下面。我這邊因為音頻是s16的,所以選擇1。

enum AVSampleFormat {
    AV_SAMPLE_FMT_NONE = -1,
    AV_SAMPLE_FMT_U8,          ///< unsigned 8 bits
    AV_SAMPLE_FMT_S16,         ///< signed 16 bits
    AV_SAMPLE_FMT_S32,         ///< signed 32 bits
    AV_SAMPLE_FMT_FLT,         ///< float
    AV_SAMPLE_FMT_DBL,         ///< double
 
    AV_SAMPLE_FMT_U8P,         ///< unsigned 8 bits, planar
    AV_SAMPLE_FMT_S16P,        ///< signed 16 bits, planar
    AV_SAMPLE_FMT_S32P,        ///< signed 32 bits, planar
    AV_SAMPLE_FMT_FLTP,        ///< float, planar
    AV_SAMPLE_FMT_DBLP,        ///< double, planar
    AV_SAMPLE_FMT_S64,         ///< signed 64 bits
    AV_SAMPLE_FMT_S64P,        ///< signed 64 bits, planar
 
    AV_SAMPLE_FMT_NB           ///< Number of sample formats. DO NOT USE if linking dynamically
};

音頻準備,輸入音頻為16k采樣率音頻。

(base) xxx@hu:~/GolandProjects/MediaRelay/data$ ffmpeg -i 1.wav 
ffmpeg version 4.2.7-0ubuntu0.1 Copyright (c) 2000-2022 the FFmpeg developers
  built with gcc 9 (Ubuntu 9.4.0-1ubuntu1~20.04.1)
  configuration: --prefix=/usr --extra-version=0ubuntu0.1 --toolchain=hardened --libdir=/usr/lib/x86_64-linux-gnu --incdir=/usr/include/x86_64-linux-gnu --arch=amd64 --enable-gpl --disable-stripping --enable-avresample --disable-filter=resample --enable-avisynth --enable-gnutls --enable-ladspa --enable-libaom --enable-libass --enable-libbluray --enable-libbs2b --enable-libcaca --enable-libcdio --enable-libcodec2 --enable-libflite --enable-libfontconfig --enable-libfreetype --enable-libfribidi --enable-libgme --enable-libgsm --enable-libjack --enable-libmp3lame --enable-libmysofa --enable-libopenjpeg --enable-libopenmpt --enable-libopus --enable-libpulse --enable-librsvg --enable-librubberband --enable-libshine --enable-libsnappy --enable-libsoxr --enable-libspeex --enable-libssh --enable-libtheora --enable-libtwolame --enable-libvidstab --enable-libvorbis --enable-libvpx --enable-libwavpack --enable-libwebp --enable-libx265 --enable-libxml2 --enable-libxvid --enable-libzmq --enable-libzvbi --enable-lv2 --enable-omx --enable-openal --enable-opencl --enable-opengl --enable-sdl2 --enable-libdc1394 --enable-libdrm --enable-libiec61883 --enable-nvenc --enable-chromaprint --enable-frei0r --enable-libx264 --enable-shared
  libavutil      56. 31.100 / 56. 31.100
  libavcodec     58. 54.100 / 58. 54.100
  libavformat    58. 29.100 / 58. 29.100
  libavdevice    58.  8.100 / 58.  8.100
  libavfilter     7. 57.100 /  7. 57.100
  libavresample   4.  0.  0 /  4.  0.  0
  libswscale      5.  5.100 /  5.  5.100
  libswresample   3.  5.100 /  3.  5.100
  libpostproc    55.  5.100 / 55.  5.100
Guessed Channel Layout for Input Stream #0.0 : mono
Input #0, wav, from '1.wav':
  Metadata:
    date            : 2020-09-28
    encoder         : Lavf58.45.100
  Duration: 00:04:01.75, bitrate: 256 kb/s
    Stream #0:0: Audio: pcm_s16le ([1][0][0][0] / 0x0001), 16000 Hz, mono, s16, 256 kb/s

執(zhí)行情況

input file format info -> AudioFormat:1,NumChannels:1,SampleRate:16000,ByteRate:32000,BlockAlign:2,BitsPerSample:16INFO : 2022/12/06 17:14:49.937547 csdn_wav_util.go:62: Create tempFile /tmp/2402235346.wav
11603961

最終音頻

(base) xxx@hu:/tmp$ ffmpeg -i 2402235346.wav 
ffmpeg version 4.2.7-0ubuntu0.1 Copyright (c) 2000-2022 the FFmpeg developers
  built with gcc 9 (Ubuntu 9.4.0-1ubuntu1~20.04.1)
  configuration: --prefix=/usr --extra-version=0ubuntu0.1 --toolchain=hardened --libdir=/usr/lib/x86_64-linux-gnu --incdir=/usr/include/x86_64-linux-gnu --arch=amd64 --enable-gpl --disable-stripping --enable-avresample --disable-filter=resample --enable-avisynth --enable-gnutls --enable-ladspa --enable-libaom --enable-libass --enable-libbluray --enable-libbs2b --enable-libcaca --enable-libcdio --enable-libcodec2 --enable-libflite --enable-libfontconfig --enable-libfreetype --enable-libfribidi --enable-libgme --enable-libgsm --enable-libjack --enable-libmp3lame --enable-libmysofa --enable-libopenjpeg --enable-libopenmpt --enable-libopus --enable-libpulse --enable-librsvg --enable-librubberband --enable-libshine --enable-libsnappy --enable-libsoxr --enable-libspeex --enable-libssh --enable-libtheora --enable-libtwolame --enable-libvidstab --enable-libvorbis --enable-libvpx --enable-libwavpack --enable-libwebp --enable-libx265 --enable-libxml2 --enable-libxvid --enable-libzmq --enable-libzvbi --enable-lv2 --enable-omx --enable-openal --enable-opencl --enable-opengl --enable-sdl2 --enable-libdc1394 --enable-libdrm --enable-libiec61883 --enable-nvenc --enable-chromaprint --enable-frei0r --enable-libx264 --enable-shared
  libavutil      56. 31.100 / 56. 31.100
  libavcodec     58. 54.100 / 58. 54.100
  libavformat    58. 29.100 / 58. 29.100
  libavdevice    58.  8.100 / 58.  8.100
  libavfilter     7. 57.100 /  7. 57.100
  libavresample   4.  0.  0 /  4.  0.  0
  libswscale      5.  5.100 /  5.  5.100
  libswresample   3.  5.100 /  3.  5.100
  libpostproc    55.  5.100 / 55.  5.100
Guessed Channel Layout for Input Stream #0.0 : mono
Input #0, wav, from '2402235346.wav':
  Duration: 00:04:01.75, bitrate: 768 kb/s
    Stream #0:0: Audio: pcm_s16le ([1][0][0][0] / 0x0001), 48000 Hz, mono, s16, 768 kb/s 

總結

其實在寫代碼過程中,有個讓我特別頭疼的東西,就是怎么把數(shù)組轉為**uint。如果大家有興趣可以研究一下ResampleByFFmpegApi2方法的轉換邏輯,會學到不少東西。

以上就是Go語言調用ffmpeg-api實現(xiàn)音頻重采樣的詳細內容,更多關于Go ffmpeg-api音頻重采樣的資料請關注腳本之家其它相關文章!

相關文章

  • Go編譯32位GNU靜態(tài)鏈接庫的方法

    Go編譯32位GNU靜態(tài)鏈接庫的方法

    Go鏈接庫系統(tǒng)的難用可謂是人盡皆知,不同Go版本編譯出來的不兼容,而且只支持GNU的,不能編譯出Windows上的dll和lib。這篇文章給大家介紹Go編譯32位GNU靜態(tài)鏈接庫的方法,感興趣的朋友一起看看吧
    2020-05-05
  • 在Go語言程序中使用gojson來解析JSON格式文件

    在Go語言程序中使用gojson來解析JSON格式文件

    這篇文章主要介紹了在Go語言程序中使用gojson來解析JSON格式文件的方法,Go是由Google開發(fā)的高人氣新興編程語言,需要的朋友可以參考下
    2015-10-10
  • Go并發(fā)編程之死鎖與活鎖的案例分析

    Go并發(fā)編程之死鎖與活鎖的案例分析

    死鎖就是在并發(fā)程序中,兩個或多個線程彼此等待對方完成操作,從而導致它們都被阻塞,并無限期地等待對方完成;活鎖就是程序一直在運行,但是無法取得進展。本文將從一些案例出發(fā),分析一下它們,希望對大家有所幫助
    2023-04-04
  • Go語言常用條件判斷空值邏輯的使用

    Go語言常用條件判斷空值邏輯的使用

    本文主要介紹了Go語言常用條件判斷空值邏輯的使用,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2023-03-03
  • 詳解Go語言如何利用高階函數(shù)寫出優(yōu)雅的代碼

    詳解Go語言如何利用高階函數(shù)寫出優(yōu)雅的代碼

    高階函數(shù)(Hiher-order?Function)定義為:滿足下列條件之一的函數(shù):接收一個或多個函數(shù)作為參數(shù);返回值是一個函數(shù)。本文為大家介紹了如何利用高階函數(shù)寫出優(yōu)雅的代碼,希望對大家有所幫助
    2023-01-01
  • golang xorm日志寫入文件中的操作

    golang xorm日志寫入文件中的操作

    這篇文章主要介紹了golang xorm日志寫入文件中的操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-12-12
  • Golang并發(fā)控制的三種實現(xiàn)方法

    Golang并發(fā)控制的三種實現(xiàn)方法

    在Golang中,有多種方式可以進行并發(fā)控制,本文詳細的介紹了三種實現(xiàn)方法,Channel優(yōu)點是實現(xiàn)簡單,清晰易懂,WaitGroup優(yōu)點是子協(xié)程個數(shù)動態(tài)可調整,Context 優(yōu)點是對子協(xié)程派生出來的孫子協(xié)程的控制,缺點是相對而言的,要結合實例應用場景進行選擇
    2023-08-08
  • Go語言中的格式化輸出占位符的用法詳解

    Go語言中的格式化輸出占位符的用法詳解

    在 Go 語言中,格式化輸出是一個非常常用的功能,特別是在處理字符串、數(shù)字和其他數(shù)據(jù)類型時,本文將詳細介紹 Go 語言中常用的格式化占位符及其用法,希望對大家有所幫助
    2024-10-10
  • go語言base64用法實例

    go語言base64用法實例

    這篇文章主要介紹了go語言base64用法,實例分析了Go語言base64編碼的實用技巧,具有一定參考借鑒價值,需要的朋友可以參考下
    2015-02-02
  • 詳解Golang實現(xiàn)請求限流的幾種辦法

    詳解Golang實現(xiàn)請求限流的幾種辦法

    這篇文章主要介紹了詳解Golang實現(xiàn)請求限流的幾種辦法,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2021-04-04

最新評論

山阴县| 阿勒泰市| 阜康市| 靖安县| 旺苍县| 奉节县| 武山县| 扎赉特旗| 景泰县| 大新县| 丰顺县| 潼南县| 施甸县| 西贡区| 尖扎县| 饶平县| 广昌县| 山东| 崇信县| 施甸县| 宁都县| 旌德县| 北票市| 乃东县| 临沂市| 福安市| 故城县| 株洲县| 徐汇区| 宜宾市| 东宁县| 从化市| 天峻县| 营口市| 云梦县| 贵定县| 宝坻区| 鄢陵县| 潞城市| 长岭县| 清丰县|