-
Notifications
You must be signed in to change notification settings - Fork 67
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Flv To mp4 #95
Comments
you should use fragment mp4. please refer to this example flv to fmp4 |
I tried this way but without success. I'm just trying to do this. If the test2_fmp4.mp4 file already exists (For example, there is a 1 minute video recording.) it should append to it and continue recording. 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"
)
func startRtmp() {
lis, err := net.Listen("tcp", ":1935")
if err != nil {
panic(err)
}
s := rtmp.NewServer()
s.LogEvent = func(c *rtmp.Conn, nc net.Conn, e int) {
es := rtmp.EventString[e]
fmt.Println(nc.LocalAddr(), nc.RemoteAddr(), es)
}
s.HandleConn = func(c *rtmp.Conn, nc net.Conn) {
fmt.Println(c.URL.Path)
if c.Publishing {
mp4filename := "test2_fmp4.mp4"
mp4file, err := os.OpenFile(mp4filename, os.O_CREATE|os.O_RDWR, 0666)
if err != nil {
fmt.Println(err)
return
}
defer mp4file.Close()
i := 0
muxer, err := mp4.CreateMp4Muxer(mp4file, mp4.WithMp4Flag(mp4.MP4_FLAG_DASH))
muxer.OnNewFragment(func(duration uint32, firstPts, firstDts uint64) {
fmt.Println("on segment", duration)
if i == 0 {
initFile, _ := os.OpenFile("init.mp4", os.O_CREATE|os.O_RDWR, 0666)
muxer.WriteInitSegment(initFile)
initFile.Close()
}
i++
muxer.ReBindWriter(mp4file)
})
if err != nil {
fmt.Println(err)
return
}
hasVideo := false
hasAudio := false
var vtid uint32
var atid uint32
defer muxer.WriteTrailer()
var asc []byte
for {
nc.SetReadDeadline(time.Now().Add(time.Second))
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()
} |
please according to this issue.
|
The problem here is that I do not record the incoming broadcast continuously. I record it piece by piece. Sometimes during recording, the broadcast from RTMP is interrupted and comes again. When it comes, I try to make it continue from the file recorded until that section. |
fmp4 satisfy your Scenario . you can append media data to the end of the fmp4 file,just like flv file |
I have the same "request". Currently when making very long recordings, as shown by @hasnhasan above, it will load all bytes into memory and then write at once. This might create OOM for very long recordings. I have seen implementations dumping the content directly in a file, and creating the appropriate headers at start, and trailer at end. Not sure if fragmented mp4 is a good solution, as these will create an init and individual segment files, where as for some usecases you would like to have one large mp4 containing all data. Not sure if this is possible with the current implementation. |
Nevermind I just fixed my "usecase" by passing in a file writer, so nothing in memory is stored, but dumped directly to filesystem. @hasnhasan I believe this would fix your issue as well. |
Hello,
The example in the file "example_covert_flv_to_mp4.go" creates and saves a new mp4 file.
I want to save it as a continuation of an existing mp4 file. Is this possible?
The text was updated successfully, but these errors were encountered: