gomedia icon indicating copy to clipboard operation
gomedia copied to clipboard

Process of merging mp4 files

Open hasnhasan opened this issue 1 year ago • 0 comments

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.

hasnhasan avatar Jun 05 '24 14:06 hasnhasan