Skip to content

Instantly share code, notes, and snippets.

@kaiiak
Last active March 23, 2024 15:28
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kaiiak/4e5f058f4289153a525a54fbc43e756a to your computer and use it in GitHub Desktop.
Save kaiiak/4e5f058f4289153a525a54fbc43e756a to your computer and use it in GitHub Desktop.
convert mp3 to pcm with golang
package ffmpeg
import (
"errors"
"fmt"
"io"
"unsafe"
"github.com/giorgisio/goav/avcodec"
"github.com/giorgisio/goav/avformat"
"github.com/giorgisio/goav/avutil"
)
func init() {
avformat.AvRegisterAll()
}
// Mp3TransformPcm depend ffmpeg
func Mp3TransformPcm(in string, w io.Writer) error {
inCtx := avformat.AvformatAllocContext()
if avformat.AvformatOpenInput(&inCtx, in, nil, nil) < 0 {
return errors.New("open file error")
}
defer inCtx.AvformatCloseInput()
if inCtx.AvformatFindStreamInfo(nil) < 0 {
return errors.New("couldn't find stream information")
}
var audioStreamIndex = -1
for i := 0; i < len(inCtx.Streams()); i++ {
if inCtx.Streams()[i].CodecParameters().AvCodecGetType() == avformat.AVMEDIA_TYPE_AUDIO {
fmt.Println("find audio index", i)
audioStreamIndex = i
}
}
codec := avcodec.AvcodecFindDecoder(avcodec.CodecId(inCtx.AudioCodecId()))
codecCtx := codec.AvcodecAllocContext3()
defer codecCtx.AvcodecClose()
pkt := avcodec.AvPacketAlloc()
defer pkt.AvPacketUnref()
if pkt == nil {
return errors.New("packet alloc error")
}
defer pkt.AvFreePacket()
utilFrame := avutil.AvFrameAlloc()
if utilFrame == nil {
return errors.New("frame alloc error")
}
defer avutil.AvFrameFree(utilFrame)
var gotName int
var index int
for inCtx.AvReadFrame(pkt) == 0 {
if pkt.StreamIndex() == audioStreamIndex {
if codecCtx.AvcodecDecodeAudio4((*avcodec.Frame)(unsafe.Pointer(utilFrame)), &gotName, pkt) < 0 {
return errors.New("codec decode audio4 error")
}
if gotName > 0 {
if _, err := w.Write(getFramBytes(utilFrame)); err != nil {
return err
}
index++
}
}
}
return nil
}
func getFramBytes(f *avutil.Frame) []byte {
data := avutil.Data(f)
var bs = make([]byte, 0, len(data))
for i := 0; i < len(data); i++ {
bs = append(bs, *data[i])
}
return bs
}
package ffmpeg
import (
"os"
"testing"
)
func TestMp3TransformPcm(t *testing.T) {
out, err := os.Create("1.pcm")
if err != nil {
t.Fatal(err)
}
defer out.Close()
if err := Mp3TransformPcm("1.mp3", out); err != nil {
t.Fatal(err)
}
}
@D-sense
Copy link

D-sense commented Jan 19, 2020

Hi @kaiiak,
Thank you for the snippet. However, I find line 53 to be throwing error. Error stack is below:

fatal error: unexpected signal during runtime execution
[signal SIGSEGV: segmentation violation code=0x1 addr=0xa8 pc=0x5c0ab9a]

runtime stack:
runtime.throw(0x410693f, 0x2a)
        /usr/local/Cellar/go/1.12.9/libexec/src/runtime/panic.go:617 +0x72
runtime.sigpanic()
        /usr/local/Cellar/go/1.12.9/libexec/src/runtime/signal_unix.go:374 +0x4a9

goroutine 1 [syscall]:
runtime.cgocall(0x40b1090, 0xc000048d88, 0x40b29f0)
        /usr/local/Cellar/go/1.12.9/libexec/src/runtime/cgocall.go:128 +0x5b fp=0xc000048d58 sp=0xc000048d20 pc=0x400564b
github.com/giorgisio/goav/avcodec._Cfunc_avcodec_decode_audio4(0x9012800, 0x8c32080, 0xc00001c0a8, 0x8c28900, 0x0)
        _cgo_gotypes.go:2173 +0x4d fp=0xc000048d88 sp=0xc000048d58 pc=0x409ed8d
github.com/giorgisio/goav/avcodec.(*Context).AvcodecDecodeAudio4.func1(0x9012800, 0x8c32080, 0xc00001c0a8, 0x8c28900, 0xc000000000)
        /Users/Oluwashola/go/pkg/mod/github.com/giorgisio/goav@v0.1.0/avcodec/context.go:100 +0xce fp=0xc000048dc0 sp=0xc000048d88 pc=0x409f1fe
github.com/giorgisio/goav/avcodec.(*Context).AvcodecDecodeAudio4(0x9012800, 0x8c32080, 0xc00001c0a8, 0x8c28900, 0x2)
        /Users/Oluwashola/go/pkg/mod/github.com/giorgisio/goav@v0.1.0/avcodec/context.go:100 +0x49 fp=0xc000048df8 sp=0xc000048dc0 pc=0x409ef99
bitbucket.org/gbedu/core/features/track/recommendation.Mp3TransformPcm(0x41029e8, 0x14, 0x0, 0x0, 0x0, 0x0)

@kaiiak
Copy link
Author

kaiiak commented Jun 6, 2020

What's your ffmpeg version?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment