gomedia
gomedia copied to clipboard
Process of merging mp4 files
I can merge 2 different mp4 files with the code below. But I cannot do the same in RTMP.
package main
import (
"fmt"
"os"
"github.com/yapingcat/gomedia/go-mp4"
)
func main() {
inputFile, _ := os.Open("1.mp4")
defer inputFile.Close()
inputFile2, _ := os.Open("2.mp4")
defer inputFile2.Close()
outputFile, _ := os.Create("output.mp4")
defer outputFile.Close()
muxer, err := mp4.CreateMp4Muxer(outputFile)
if err != nil {
fmt.Println(err)
return
}
muxer.AddVideoTrack(mp4.MP4_CODEC_H264)
muxer.AddAudioTrack(mp4.MP4_CODEC_AAC)
demuxer := mp4.CreateMp4Demuxer(inputFile)
demuxer.ReadHead()
for {
pkt, err := demuxer.ReadPacket()
if err != nil {
break
}
muxer.Write(uint32(pkt.TrackId), pkt.Data, pkt.Pts, pkt.Dts)
}
demuxer2 := mp4.CreateMp4Demuxer(inputFile2)
demuxer2.ReadHead()
for {
pkt, err := demuxer2.ReadPacket()
if err != nil {
break
}
muxer.Write(uint32(pkt.TrackId), pkt.Data, pkt.Pts, pkt.Dts)
}
err = muxer.WriteTrailer()
if err != nil {
panic(err)
}
}
But when I combine it with the recording from RTMP. At the end of the 1.mp4 file, it adds the data from RTMP to the end of the file. How can I overcome this problem?
package main
import (
"encoding/binary"
"fmt"
"net"
"os"
"time"
"github.com/notedit/rtmp/av"
"github.com/notedit/rtmp/format/rtmp"
"github.com/yapingcat/gomedia/go-codec"
"github.com/yapingcat/gomedia/go-mp4"
)
type stream struct {
videoSeq av.Packet
audioSeq av.Packet
conn *rtmp.Conn
}
func startRtmp() {
lis, err := net.Listen("tcp", ":1935")
if err != nil {
panic(err)
}
s := rtmp.NewServer()
inputFile, _ := os.Open("1.mp4")
defer inputFile.Close()
mp4filename := "output.mp4"
mp4file, _ := os.OpenFile(mp4filename, os.O_CREATE|os.O_RDWR, 0666)
defer mp4file.Close()
muxer, err := mp4.CreateMp4Muxer(mp4file)
if err != nil {
fmt.Println(err)
return
}
muxer.AddVideoTrack(mp4.MP4_CODEC_H264)
muxer.AddAudioTrack(mp4.MP4_CODEC_AAC)
demuxer := mp4.CreateMp4Demuxer(inputFile)
demuxer.ReadHead()
for {
pkt, err := demuxer.ReadPacket()
if err != nil {
break
}
muxer.Write(uint32(pkt.TrackId), pkt.Data, pkt.Pts, pkt.Dts)
}
s.HandleConn = func(c *rtmp.Conn, nc net.Conn) {
if !c.Publishing {
nc.Close()
return
}
hasVideo := false
hasAudio := false
var vtid uint32
var atid uint32
defer muxer.WriteTrailer()
var asc []byte
for {
pkt, err := c.ReadPacket()
if err != nil {
fmt.Println(err)
return
}
pts := pkt.CTime.Milliseconds() + pkt.Time.Milliseconds()
dts := pkt.Time.Milliseconds()
switch pkt.Type {
case av.H264DecoderConfig:
if !hasVideo {
vtid = muxer.AddVideoTrack(mp4.MP4_CODEC_H264)
hasVideo = true
}
tmpspss, tmpppss := codec.CovertExtradata(pkt.Data)
fmt.Println(len(tmpspss), len(tmpppss))
pts := pkt.CTime + pkt.Time
frame := make([]byte, 0, len(tmpspss[0])+len(tmpppss[0]))
frame = append(frame, tmpspss[0]...)
frame = append(frame, tmpppss[0]...)
codec.ShowPacketHexdump(tmpspss[0])
fmt.Println(codec.GetSPSIdWithStartCode(tmpspss[0]))
muxer.Write(vtid, frame, uint64(pts), uint64(dts))
case av.H264:
for len(pkt.Data) > 0 {
naluSize := binary.BigEndian.Uint32(pkt.Data[:4])
codec.ShowPacketHexdump(pkt.Data[:6])
codec.CovertAVCCToAnnexB(pkt.Data)
muxer.Write(vtid, pkt.Data[:4+naluSize], uint64(pts), uint64(dts))
pkt.Data = pkt.Data[4+naluSize:]
}
//fmt.Println("h264 frame pts ", pts, "dts ", dts)
case av.AACDecoderConfig:
if !hasAudio {
atid = muxer.AddAudioTrack(mp4.MP4_CODEC_AAC)
hasAudio = true
}
asc = make([]byte, len(pkt.Data))
copy(asc, pkt.Data)
case av.AAC:
adts, err := codec.ConvertASCToADTS(asc, len(pkt.Data)+7)
if err != nil {
return
}
//fmt.Println("aac frame pts ", pts, "dts ", dts)
adts_frame := append(adts.Encode(), pkt.Data...)
muxer.Write(atid, adts_frame, uint64(pts), uint64(dts))
}
}
}
for {
nc, err := lis.Accept()
if err != nil {
time.Sleep(time.Second)
continue
}
go s.HandleNetConn(nc)
}
}
func main() {
startRtmp()
}
Thank you very much for your help.