GoToSocial/vendor/github.com/abema/go-mp4/README.md

155 lines
3.8 KiB
Markdown
Raw Normal View History

go-mp4
------
[![Go Reference](https://pkg.go.dev/badge/github.com/abema/go-mp4.svg)](https://pkg.go.dev/github.com/abema/go-mp4)
![Test](https://github.com/abema/go-mp4/actions/workflows/test.yml/badge.svg)
[![Coverage Status](https://coveralls.io/repos/github/abema/go-mp4/badge.svg)](https://coveralls.io/github/abema/go-mp4)
[![Go Report Card](https://goreportcard.com/badge/github.com/abema/go-mp4)](https://goreportcard.com/report/github.com/abema/go-mp4)
go-mp4 is Go library and CLI tool which provide low-level I/O interfaces of MP4.
This library supports you to parse or build any MP4 boxes(atoms) directly.
## Integration with your Go application
### Reading
You can parse MP4 file as follows:
```go
// expand all boxes
_, err := mp4.ReadBoxStructure(file, func(h *mp4.ReadHandle) (interface{}, error) {
fmt.Println("depth", len(h.Path))
// Box Type (e.g. "mdhd", "tfdt", "mdat")
fmt.Println("type", h.BoxInfo.Type.String())
// Box Size
fmt.Println("size", h.BoxInfo.Size)
if h.BoxInfo.IsSupportedType() {
// Payload
box, _, err := h.ReadPayload()
if err != nil {
return nil, err
}
str, err := mp4.Stringify(box, h.BoxInfo.Context)
if err != nil {
return nil, err
}
fmt.Println("payload", str)
// Expands children
return h.Expand()
}
return nil, nil
})
```
```go
// extract specific boxes
boxes, err := mp4.ExtractBoxWithPayload(file, nil, mp4.BoxPath{mp4.BoxTypeMoov(), mp4.BoxTypeTrak(), mp4.BoxTypeTkhd()})
if err != nil {
:
}
for _, box := range boxes {
tkhd := box.Payload.(*mp4.Tkhd)
fmt.Println("track ID:", tkhd.TrackID)
}
```
```go
// get basic informations
info, err := mp4.Probe(bufseekio.NewReadSeeker(file, 1024, 4))
if err != nil {
:
}
fmt.Println("track num:", len(info.Tracks))
```
### Writing
Writer helps you to write box tree.
The following sample code edits emsg box and writes to another file.
```go
r := bufseekio.NewReadSeeker(inputFile, 128*1024, 4)
w := mp4.NewWriter(outputFile)
_, err = mp4.ReadBoxStructure(r, func(h *mp4.ReadHandle) (interface{}, error) {
switch h.BoxInfo.Type {
case mp4.BoxTypeEmsg():
// write box size and box type
_, err := w.StartBox(&h.BoxInfo)
if err != nil {
return nil, err
}
// read payload
box, _, err := h.ReadPayload()
if err != nil {
return nil, err
}
// update MessageData
emsg := box.(*mp4.Emsg)
emsg.MessageData = []byte("hello world")
// write box playload
if _, err := mp4.Marshal(w, emsg, h.BoxInfo.Context); err != nil {
return nil, err
}
// rewrite box size
_, err = w.EndBox()
return nil, err
default:
// copy all
return nil, w.CopyBox(r, &h.BoxInfo)
}
})
```
### User-defined Boxes
You can create additional box definition as follows:
```go
func BoxTypeXxxx() BoxType { return mp4.StrToBoxType("xxxx") }
func init() {
mp4.AddBoxDef(&Xxxx{}, 0)
}
type Xxxx struct {
FullBox `mp4:"0,extend"`
UI32 uint32 `mp4:"1,size=32"`
ByteArray []byte `mp4:"2,size=8,len=dynamic"`
}
func (*Xxxx) GetType() BoxType {
return BoxTypeXxxx()
}
```
### Buffering
go-mp4 has no buffering feature for I/O.
If you should reduce Read function calls, you can wrap the io.ReadSeeker by [bufseekio](https://github.com/sunfish-shogi/bufseekio).
## Command Line Tool
Install mp4tool as follows:
```sh
go install github.com/abema/go-mp4/cmd/mp4tool@latest
mp4tool -help
```
For example, `mp4tool dump MP4_FILE_NAME` command prints MP4 box tree as follows:
```
[moof] Size=504
[mfhd] Size=16 Version=0 Flags=0x000000 SequenceNumber=1
[traf] Size=480
[tfhd] Size=28 Version=0 Flags=0x020038 TrackID=1 DefaultSampleDuration=9000 DefaultSampleSize=33550 DefaultSampleFlags=0x1010000
[tfdt] Size=20 Version=1 Flags=0x000000 BaseMediaDecodeTimeV1=0
[trun] Size=424 ... (use -a option to show all)
[mdat] Size=44569 Data=[...] (use -mdat option to expand)
```