Last active
October 22, 2022 02:20
-
-
Save linnv/d00509f38a5ffd3e4d1fd0d11f371768 to your computer and use it in GitHub Desktop.
### A demo that shows how to exact RTP payload and convert to WAV, there are some key points on comment
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module rtpdemo | |
go 1.18 | |
require ( | |
github.com/go-audio/audio v1.0.0 | |
github.com/go-audio/wav v1.1.0 | |
github.com/jart/gosip v0.0.0-20220818224804-29801cedf805 | |
github.com/linnv/logx v1.3.5 | |
github.com/zaf/g711 v0.0.0-20220109202201-cf0017bf0359 | |
) | |
require ( | |
github.com/go-audio/riff v1.0.0 // indirect | |
github.com/linnv/bufferlog v1.2.0 // indirect | |
github.com/pkg/errors v0.8.1 // indirect | |
) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"bytes" | |
"encoding/binary" | |
"fmt" | |
"io" | |
"io/ioutil" | |
"log" | |
"net" | |
"os" | |
"os/signal" | |
"syscall" | |
"github.com/go-audio/audio" | |
"github.com/go-audio/wav" | |
"github.com/jart/gosip/rtp" | |
"github.com/linnv/logx" | |
"github.com/zaf/g711" | |
) | |
func pcm2wav() { | |
// Read raw PCM data from input file. | |
in, err := os.Open(outName) | |
if err != nil { | |
log.Fatal(err) | |
} | |
// Output file. | |
out, err := os.Create(outName + ".wav") | |
if err != nil { | |
log.Fatal(err) | |
} | |
defer out.Close() | |
// 8 kHz, 16 bit, 1 channel, WAV. | |
e := wav.NewEncoder(out, 8000, 16, 1, 1) | |
// Create new audio.IntBuffer. | |
audioBuf, err := newAudioIntBuffer(in) | |
if err != nil { | |
log.Fatal(err) | |
} | |
// Write buffer to output file. This writes a RIFF header and the PCM chunks from the audio.IntBuffer. | |
if err := e.Write(audioBuf); err != nil { | |
log.Fatal(err) | |
} | |
if err := e.Close(); err != nil { | |
log.Fatal(err) | |
} | |
} | |
func newAudioIntBuffer(r io.Reader) (*audio.IntBuffer, error) { | |
buf := audio.IntBuffer{ | |
Format: &audio.Format{ | |
NumChannels: 1, | |
SampleRate: 8000, | |
}, | |
} | |
for { | |
var sample int16 | |
err := binary.Read(r, binary.LittleEndian, &sample) | |
switch { | |
case err == io.EOF: | |
return &buf, nil | |
case err != nil: | |
return nil, err | |
} | |
buf.Data = append(buf.Data, int(sample)) | |
} | |
} | |
const outName = "/Users/jialin/Downloads/rtp-l-payload/decodeByGocode.alaw" | |
//Decode implements ... | |
func Decode() error { | |
input, err := os.Open("/Users/jialin/Downloads/rtp-l-payload/left-go-payload.raw") | |
if err != nil { | |
return err | |
} | |
defer input.Close() | |
decoder, err := g711.NewAlawDecoder(input) | |
if err != nil { | |
return err | |
} | |
outFile, err := os.Create(outName) | |
if err != nil { | |
return err | |
} | |
defer outFile.Close() | |
_, err = io.Copy(outFile, decoder) | |
return err | |
} | |
func ExactPayload() { | |
port := 30000 | |
fmt.Println() | |
sigChan := make(chan os.Signal, 2) | |
exit := make(chan struct{}) | |
signal.Notify(sigChan, syscall.SIGHUP, syscall.SIGINT, syscall.SIGQUIT, syscall.SIGTERM) | |
log.Print("use c-c to exit: \n") | |
count := 0 | |
var underBuf []byte | |
buf := bytes.NewBuffer(underBuf) | |
go func() { | |
logx.Debugf("port: %+v\n", port) | |
conn, err := net.ListenUDP("udp", &net.UDPAddr{Port: port}) | |
if err != nil { | |
log.Fatalf("Udp Service listen report udp fail:%v", err) | |
} | |
defer conn.Close() | |
for { | |
select { | |
case <-exit: | |
return | |
default: | |
} | |
data := make([]byte, 1024*4) | |
n, remoteAddr, err := conn.ReadFromUDP(data) | |
if err == nil { | |
const headerSize = 12 | |
if n > headerSize { | |
bufn, bufErr := buf.Write(data[12:n]) | |
logx.Debugf("bufn : %+v bufErr:%s\n", bufn, bufErr) | |
} | |
var rtpHeader rtp.Header | |
err = rtpHeader.Read(data) | |
if err != nil { | |
logx.Warnf("err: %+v\n", err) | |
} | |
logx.Debugf("rtpHeader: %+v\n", rtpHeader) | |
count += n | |
// ... do something | |
logx.Debugf("n: %+v remoteAddr %s err %s\n", n, remoteAddr, err) | |
logx.Debugf("total: %+v\n", count) | |
// conn.WriteToUDP(data[:n], remoteAddr) | |
} else { | |
logx.Debugf("n: %+v remoteAddr %s err %s\n", n, remoteAddr, err) | |
} | |
} | |
}() | |
<-sigChan | |
close(exit) | |
logx.Debugf("total: %+v\n", count) | |
logx.Debugf("buf: %+v\n", buf.Len()) | |
if err := ioutil.WriteFile("./go-payload.raw", buf.Bytes(), 0622); err != nil { | |
logx.Errorf("err: %+v\n", err) | |
} | |
logx.Flush() | |
os.Exit(0) | |
} | |
func main() { | |
if err := Decode(); err != nil { | |
logx.Errorf("err: %+v\n", err) | |
} | |
pcm2wav() | |
logx.Flush() | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
the finally output WAV file can be played on VLC or other media player