mp4

package module
v0.2.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 1, 2026 License: MIT Imports: 5 Imported by: 0

README

mp4

ISOBMFF/MP4 container library with fragmented MP4 support.

Install

go get github.com/tetsuo/mp4

Usage

Reading boxes

Scanner walks the top-level boxes of a file without loading their contents. Load only the boxes you need, then use Reader to descend into a box and read typed fields.

f, _ := os.Open("video.mp4")
defer f.Close()

sc := mp4.NewScanner(f)
for sc.Next() {
    e := sc.Entry()
    fmt.Printf("%s size=%d offset=%d\n", e.Type, e.Size, e.Offset)

    if e.Type == mp4.TypeMoov {
        buf := make([]byte, e.DataSize())
        if err := sc.ReadBody(buf); err != nil {
            log.Fatal(err)
        }

        r := mp4.NewReader(buf)
        r.Enter() // descend into moov
        for r.Next() {
            if r.Type() == mp4.TypeMvhd {
                timescale, duration, _ := r.ReadMvhd()
                fmt.Printf("timescale=%d duration=%d\n", timescale, duration)
            }
        }
        r.Exit()
    }
}
if err := sc.Err(); err != nil {
    log.Fatal(err)
}
Writing boxes

Writer encodes boxes into a caller-provided buffer. StartBox and EndBox handle size backpatching for nested boxes:

buf := make([]byte, 0, 1024)
w := mp4.NewWriter(buf)

w.WriteFtyp([4]byte{'i', 's', 'o', 'm'}, 0, [][4]byte{{'m', 'p', '4', '2'}})

w.StartBox(mp4.TypeMoov)
w.WriteMvhd(1000, 30000, 3)
w.EndBox()

if err := w.Err(); err != nil {
    log.Fatal(err)
}
output := w.Bytes()
Parsing tracks

The track package resolves the sample tables inside a moov box into a flat list of samples. Each sample carries its byte offset, size, decode and presentation timestamps, and sync (keyframe) flag.

tracks, duration, err := track.ParseTracks(moovBuf)
if err != nil {
    log.Fatal(err)
}

for _, t := range tracks {
    fmt.Printf("track %d: codec=%s samples=%d\n", t.ID, t.Codec(), len(t.Samples))
    for _, s := range t.Samples {
        _ = s.Offset   // byte offset in the file
        _ = s.Size()   // sample size in bytes
        _ = s.PTS()    // presentation timestamp
        _ = s.IsSync() // keyframe
    }
}
Fragmenting to fMP4

The fragment package reads a standard MP4 file and produces an init segment (ftyp+moov) followed by media fragments (moof+mdat pairs), suitable for HLS or DASH.

f, _ := os.Open("video.mp4")
defer f.Close()

reader, initSeg, err := fragment.NewReader(f)
if err != nil {
    log.Fatal(err)
}

writer := fragment.NewWriter(os.Stdout)
if err := writer.WriteInit(initSeg); err != nil {
    log.Fatal(err)
}

for {
    frag, err := reader.ReadFragment()
    if err == io.EOF {
        break
    }
    if err != nil {
        log.Fatal(err)
    }
    if err := writer.WriteFragment(frag, f); err != nil {
        log.Fatal(err)
    }
}

Use Reader.SetTimeRange to limit output to a time window, or Reader.Seek to reposition before reading fragments.

Examples

The cmd directory contains small programs built on these packages:

  • mp4dump prints the box structure of a file as text or JSON.
  • mp4probe displays track and fragment information.
  • mp4remux remuxes a file into fragmented MP4.

Performance

goos: darwin
goarch: arm64
pkg: github.com/tetsuo/mp4
cpu: Apple M4 Pro
BenchmarkReaderParse
BenchmarkReaderParse-12        3547731        317.4 ns/op    58353.33 MB/s        0 B/op        0 allocs/op
BenchmarkStszIter
BenchmarkStszIter-12            897819       1230.0 ns/op     2348.81 MB/s        0 B/op        0 allocs/op
BenchmarkWriterBuild
BenchmarkWriterBuild-12       15768681         76.26 ns/op                        0 B/op        0 allocs/op
BenchmarkScannerParse
BenchmarkScannerParse-12        343438       3512.0 ns/op     5274.38 MB/s        0 B/op        0 allocs/op
PASS
ok    github.com/tetsuo/mp4 5.023s

Documentation

Overview

Package mp4 provides support for the ISO base media file format and fragmented MP4 streams.

Index

Constants

View Source
const (
	TrunDataOffsetPresent                  = 0x000001
	TrunFirstSampleFlagsPresent            = 0x000004
	TrunSampleDurationPresent              = 0x000100
	TrunSampleSizePresent                  = 0x000200
	TrunSampleFlagsPresent                 = 0x000400
	TrunSampleCompositionTimeOffsetPresent = 0x000800
)

Trun flags.

View Source
const (
	TfhdBaseDataOffsetPresent         = 0x000001
	TfhdSampleDescriptionIndexPresent = 0x000002
	TfhdDefaultSampleDurationPresent  = 0x000008
	TfhdDefaultSampleSizePresent      = 0x000010
	TfhdDefaultSampleFlagsPresent     = 0x000020
	TfhdDurationIsEmpty               = 0x010000
	TfhdDefaultBaseIsMoof             = 0x020000
)

Tfhd flags (Track Fragment Header Box).

Variables

View Source
var (
	TypeFtyp = BoxType{'f', 't', 'y', 'p'} // File type and compatibility
	TypeStyp = BoxType{'s', 't', 'y', 'p'} // Segment type (fragmented MP4)
)

Known box types.

View Source
var (
	TypeMoov = BoxType{'m', 'o', 'o', 'v'} // Movie metadata container
	TypeMvhd = BoxType{'m', 'v', 'h', 'd'} // Movie header (timescale, duration)
	TypeTrak = BoxType{'t', 'r', 'a', 'k'} // Track container
	TypeTkhd = BoxType{'t', 'k', 'h', 'd'} // Track header (ID, dimensions)
	TypeTref = BoxType{'t', 'r', 'e', 'f'} // Track reference container
	TypeTrgr = BoxType{'t', 'r', 'g', 'r'} // Track grouping indication
	TypeEdts = BoxType{'e', 'd', 't', 's'} // Edit list container
	TypeElst = BoxType{'e', 'l', 's', 't'} // Edit list entries
	TypeMdia = BoxType{'m', 'd', 'i', 'a'} // Media information container
	TypeMdhd = BoxType{'m', 'd', 'h', 'd'} // Media header (timescale, duration)
	TypeHdlr = BoxType{'h', 'd', 'l', 'r'} // Handler reference (vide/soun)
	TypeElng = BoxType{'e', 'l', 'n', 'g'} // Extended language tag
	TypeMinf = BoxType{'m', 'i', 'n', 'f'} // Media information container
	TypeVmhd = BoxType{'v', 'm', 'h', 'd'} // Video media header
	TypeSmhd = BoxType{'s', 'm', 'h', 'd'} // Sound media header
	TypeHmhd = BoxType{'h', 'm', 'h', 'd'} // Hint media header
	TypeSthd = BoxType{'s', 't', 'h', 'd'} // Subtitle media header
	TypeNmhd = BoxType{'n', 'm', 'h', 'd'} // Null media header
	TypeDinf = BoxType{'d', 'i', 'n', 'f'} // Data information container
	TypeDref = BoxType{'d', 'r', 'e', 'f'} // Data reference (URL/URN entries)
)

Movie structure boxes (moov and children).

View Source
var (
	TypeStbl = BoxType{'s', 't', 'b', 'l'} // Sample table container
	TypeStsd = BoxType{'s', 't', 's', 'd'} // Sample descriptions (codec config)
	TypeStts = BoxType{'s', 't', 't', 's'} // Decoding time-to-sample
	TypeCtts = BoxType{'c', 't', 't', 's'} // Composition time-to-sample
	TypeCslg = BoxType{'c', 's', 'l', 'g'} // Composition to decode timeline mapping
	TypeStsc = BoxType{'s', 't', 's', 'c'} // Sample-to-chunk mapping
	TypeStsz = BoxType{'s', 't', 's', 'z'} // Sample sizes
	TypeStz2 = BoxType{'s', 't', 'z', '2'} // Compact sample sizes
	TypeStco = BoxType{'s', 't', 'c', 'o'} // Chunk offsets (32-bit)
	TypeCo64 = BoxType{'c', 'o', '6', '4'} // Chunk offsets (64-bit)
	TypeStss = BoxType{'s', 't', 's', 's'} // Sync sample table (keyframes)
	TypeStsh = BoxType{'s', 't', 's', 'h'} // Shadow sync sample table
	TypePadb = BoxType{'p', 'a', 'd', 'b'} // Padding bits
	TypeStdp = BoxType{'s', 't', 'd', 'p'} // Sample degradation priority
	TypeSdtp = BoxType{'s', 'd', 't', 'p'} // Sample dependency type
	TypeSbgp = BoxType{'s', 'b', 'g', 'p'} // Sample-to-group
	TypeSgpd = BoxType{'s', 'g', 'p', 'd'} // Sample group description
	TypeSubs = BoxType{'s', 'u', 'b', 's'} // Sub-sample information
	TypeSaiz = BoxType{'s', 'a', 'i', 'z'} // Sample auxiliary information sizes
	TypeSaio = BoxType{'s', 'a', 'i', 'o'} // Sample auxiliary information offsets
)

Sample table boxes (stbl children).

View Source
var (
	TypeMvex = BoxType{'m', 'v', 'e', 'x'} // Movie extends (signals fragmented file)
	TypeMehd = BoxType{'m', 'e', 'h', 'd'} // Movie extends header (fragment duration)
	TypeTrex = BoxType{'t', 'r', 'e', 'x'} // Track extends defaults
	TypeLeva = BoxType{'l', 'e', 'v', 'a'} // Level assignment
	TypeMoof = BoxType{'m', 'o', 'o', 'f'} // Movie fragment container
	TypeMfhd = BoxType{'m', 'f', 'h', 'd'} // Movie fragment header (sequence number)
	TypeTraf = BoxType{'t', 'r', 'a', 'f'} // Track fragment container
	TypeTfhd = BoxType{'t', 'f', 'h', 'd'} // Track fragment header
	TypeTfdt = BoxType{'t', 'f', 'd', 't'} // Track fragment decode time
	TypeTrun = BoxType{'t', 'r', 'u', 'n'} // Track run (per-sample metadata)
	TypeSidx = BoxType{'s', 'i', 'd', 'x'} // Segment index
	TypeEmsg = BoxType{'e', 'm', 's', 'g'} // Event message
)

Fragment boxes (moof and children, mvex).

View Source
var (
	TypeMeta = BoxType{'m', 'e', 't', 'a'} // Metadata container
	TypeUdta = BoxType{'u', 'd', 't', 'a'} // User data container
)

Metadata boxes.

View Source
var (
	TypeMdat = BoxType{'m', 'd', 'a', 't'} // Media data payload
	TypeFree = BoxType{'f', 'r', 'e', 'e'} // Free space (can be skipped)
	TypeSkip = BoxType{'s', 'k', 'i', 'p'} // Free space (can be skipped)
)

Data boxes.

View Source
var (
	TypeAvc1 = BoxType{'a', 'v', 'c', '1'} // AVC/H.264 visual sample entry
	TypeAvcC = BoxType{'a', 'v', 'c', 'C'} // AVC decoder configuration record
	TypeAv01 = BoxType{'a', 'v', '0', '1'} // AV1 visual sample entry
	TypeAv1C = BoxType{'a', 'v', '1', 'C'} // AV1 codec configuration record
	TypeBtrt = BoxType{'b', 't', 'r', 't'} // MPEG-4 bit rate
	TypePasp = BoxType{'p', 'a', 's', 'p'} // Pixel aspect ratio
	TypeMp4a = BoxType{'m', 'p', '4', 'a'} // MPEG-4 audio sample entry
	TypeEsds = BoxType{'e', 's', 'd', 's'} // ES descriptor
)

Sample entry boxes (children of stsd).

View Source
var ErrBoxTooLarge = errors.New("mp4: box size exceeds 4GB limit")

ErrBoxTooLarge is returned by Writer.Err when a box exceeds the 4 GB limit for standard (32-bit) box sizes.

Functions

func IsContainerBox added in v0.2.0

func IsContainerBox(t BoxType) bool

IsContainerBox returns true if the box type is a container that holds child boxes.

func IsFullBox added in v0.2.0

func IsFullBox(t BoxType) bool

IsFullBox returns true if the box type has version and flags fields.

func ReadAvcC added in v0.2.0

func ReadAvcC(data []byte) string

ReadAvcC extracts the codec profile string from avcC box data. Returns a string like "64001f" for use in MIME type codec parameters.

func ReadEsdsCodec added in v0.2.0

func ReadEsdsCodec(data []byte) string

ReadEsdsCodec extracts the MIME codec string from esds box data. It parses the MPEG-4 descriptor chain to find the OTI (Object Type Indication) and audio configuration. Returns a string like "40.2" for AAC-LC.

Types

type AudioSampleEntry

type AudioSampleEntry struct {
	DataReferenceIndex uint16
	ChannelCount       uint16
	SampleSize         uint16
	SampleRate         uint32 // 16.16 fixed point
	ChildOffset        int    // byte offset within data where child boxes begin
}

AudioSampleEntry holds parsed fields from an audio sample entry (e.g. mp4a).

func ReadAudioSampleEntry added in v0.2.0

func ReadAudioSampleEntry(data []byte) AudioSampleEntry

ReadAudioSampleEntry parses an audio sample entry from box data. Child boxes (e.g. esds) start at ChildOffset within the data.

type BoxType

type BoxType [4]byte

BoxType is a 4-byte box type identifier.

func (BoxType) String

func (t BoxType) String() string

type Co64Iter added in v0.2.0

type Co64Iter struct {
	// contains filtered or unexported fields
}

Co64Iter iterates over uint64 chunk offsets in a co64 box.

func NewCo64Iter added in v0.2.0

func NewCo64Iter(data []byte) Co64Iter

NewCo64Iter creates an iterator from co64 box data.

func (*Co64Iter) Count added in v0.2.0

func (it *Co64Iter) Count() uint32

Count returns the total number of entries.

func (*Co64Iter) Next added in v0.2.0

func (it *Co64Iter) Next() (uint64, bool)

Next returns the next chunk offset. Returns (0, false) when done.

type CttsEntry added in v0.2.0

type CttsEntry struct {
	Count  uint32
	Offset int32 // Signed offset (version 1), or unsigned treated as signed (version 0)
}

CttsEntry is a composition offset entry.

type CttsIter added in v0.2.0

type CttsIter struct {
	// contains filtered or unexported fields
}

CttsIter iterates over ctts entries.

func NewCttsIter added in v0.2.0

func NewCttsIter(data []byte, version uint8) CttsIter

NewCttsIter creates an iterator from ctts box data. version should be 0 or 1 from the ctts box version field. Version 0: offsets are uint32 (but interpreted as composition time offset) Version 1: offsets are int32 (signed composition time offset)

func (*CttsIter) Count added in v0.2.0

func (it *CttsIter) Count() uint32

Count returns the total number of entries.

func (*CttsIter) Next added in v0.2.0

func (it *CttsIter) Next() (CttsEntry, bool)

Next returns the next entry. Returns false when done.

type ElstEntry

type ElstEntry struct {
	SegmentDuration uint64
	MediaTime       int64
	MediaRateInt    int16
	MediaRateFrac   int16
}

ElstEntry is an edit list entry.

type ElstIter added in v0.2.0

type ElstIter struct {
	// contains filtered or unexported fields
}

ElstIter iterates over elst entries.

func NewElstIter added in v0.2.0

func NewElstIter(data []byte, version uint8) ElstIter

NewElstIter creates an iterator from elst box data with the given version.

func (*ElstIter) Count added in v0.2.0

func (it *ElstIter) Count() uint32

Count returns the total number of entries.

func (*ElstIter) Next added in v0.2.0

func (it *ElstIter) Next() (ElstEntry, bool)

Next returns the next entry. Returns false when done.

type FtypInfo added in v0.2.0

type FtypInfo struct {
	MajorBrand   [4]byte
	MinorVersion uint32
	Compatible   [][4]byte
}

FtypInfo holds parsed fields from an ftyp box.

func ReadFtyp added in v0.2.0

func ReadFtyp(data []byte) FtypInfo

ReadFtyp parses an ftyp box.

type Reader added in v0.2.0

type Reader struct {
	// contains filtered or unexported fields
}

Reader provides hierarchical, in-memory parsing of box data. After loading a box's bytes (e.g., from Scanner), create a Reader to iterate children, descend into containers, and extract typed fields.

Iterating over top-level boxes:

r := mp4.NewReader(buf)
for r.Next() {
    fmt.Printf("box: %s size: %d\n", r.Type(), r.Size())
}

For container boxes, use Enter/Exit to descend into children:

for r.Next() {
    if r.Type() == mp4.TypeMoov {
        r.Enter()              // descend into moov
        for r.Next() {         // iterate moov children
            // process trak, mvhd, etc.
        }
        r.Exit()               // return to top level
    }
}

Some boxes have an entry count before child boxes (stsd, dref). Use Skip(4) after Enter to skip past the count field:

r.Enter()
r.Skip(4) // skip entry count
for r.Next() {
    // process entries
}
r.Exit()

Sample entry boxes have fixed-size headers before child boxes. Use Skip with the header size (avc1=78, mp4a=28):

r.Enter()
r.Skip(78)          // skip avc1 fixed header
for r.Next() {
    // process avcC, pasp, etc.
}
r.Exit()

func NewReader added in v0.2.0

func NewReader(buf []byte) Reader

NewReader creates a Reader for the given buffer.

func (*Reader) Data added in v0.2.0

func (r *Reader) Data() []byte

Data returns the current box's data (after all headers). Note that, the returned slice points into the original buffer.

func (*Reader) DataOffset added in v0.2.0

func (r *Reader) DataOffset() int

DataOffset returns the byte offset where the current box's data begins.

func (*Reader) Depth added in v0.2.0

func (r *Reader) Depth() int

Depth returns the current nesting depth (0 at top level).

func (*Reader) Enter added in v0.2.0

func (r *Reader) Enter()

Enter descends into the current container box to iterate its children. After Enter, call Next to advance to the first child box. Call Exit when done to return to the parent level.

For boxes like stsd or dref that have an entry count before child boxes, call Skip(4) after Enter to skip past the count field.

For sample entry boxes like avc1 (78 bytes) or mp4a (28 bytes), call Skip with the fixed header size after Enter to reach child boxes.

func (*Reader) EntryCount added in v0.2.0

func (r *Reader) EntryCount() uint32

EntryCount reads the uint32 entry count at the start of box data. Used for boxes like stsd and dref that begin with a count field.

func (*Reader) Exit added in v0.2.0

func (r *Reader) Exit()

Exit returns to the parent container level. After Exit, the next call to Next will advance to the next sibling.

func (*Reader) Flags added in v0.2.0

func (r *Reader) Flags() uint32

Flags returns the flags field for full boxes.

func (*Reader) HeaderSize added in v0.2.0

func (r *Reader) HeaderSize() int

HeaderSize returns the size of the current box's header in bytes.

func (*Reader) Next added in v0.2.0

func (r *Reader) Next() bool

Next advances to the next sibling box. Returns false if no more boxes.

func (*Reader) Offset added in v0.2.0

func (r *Reader) Offset() int

Offset returns the byte offset of the current box's start in the buffer.

func (*Reader) RawBox added in v0.2.0

func (r *Reader) RawBox() []byte

RawBox returns the entire current box including headers. Note that, the returned slice points into the original buffer.

func (*Reader) ReadElst added in v0.2.0

func (r *Reader) ReadElst() (mediaTime int64, ok bool)

ReadElst extracts the media time of the first edit list entry, in the media timescale. It returns the media time and whether an entry was present.

func (*Reader) ReadHdlr added in v0.2.0

func (r *Reader) ReadHdlr() [4]byte

ReadHdlr extracts the handler type from an hdlr box. Returns the 4-byte handler type string.

func (*Reader) ReadHdlrName added in v0.2.0

func (r *Reader) ReadHdlrName() string

ReadHdlrName extracts the handler name from an hdlr box.

func (*Reader) ReadMdhd added in v0.2.0

func (r *Reader) ReadMdhd() (timescale uint32, duration uint64, language uint16)

ReadMdhd extracts key fields from an mdhd box. Returns timescale, duration, and language code.

func (*Reader) ReadMehd added in v0.2.0

func (r *Reader) ReadMehd() (fragmentDuration uint64)

ReadMehd extracts the fragment duration from an mehd box.

func (*Reader) ReadMfhd added in v0.2.0

func (r *Reader) ReadMfhd() (sequenceNumber uint32)

ReadMfhd extracts the sequence number from an mfhd box.

func (*Reader) ReadMvhd added in v0.2.0

func (r *Reader) ReadMvhd() (timescale uint32, duration uint64, nextTrackId uint32)

ReadMvhd extracts key fields from an mvhd box. Returns timescale, duration, and nextTrackId.

func (*Reader) ReadTfdt added in v0.2.0

func (r *Reader) ReadTfdt() (baseMediaDecodeTime uint64)

ReadTfdt extracts the base media decode time from a tfdt box.

func (*Reader) ReadTfhd added in v0.2.0

func (r *Reader) ReadTfhd() (trackId uint32)

ReadTfhd extracts the track ID from a tfhd box.

func (*Reader) ReadTkhd added in v0.2.0

func (r *Reader) ReadTkhd() (trackId uint32, duration uint64, width, height uint32)

ReadTkhd extracts key fields from a tkhd box. Returns trackId, duration, width, height. Width and height are 16.16 fixed-point values; shift right by 16 for pixels.

func (*Reader) ReadTrex added in v0.2.0

func (r *Reader) ReadTrex() (trackId, defSampleDescIdx, defSampleDuration, defSampleSize, defSampleFlags uint32)

ReadTrex extracts fields from a trex box. Returns trackId, default sample description index, default sample duration, default sample size, and default sample flags.

func (*Reader) Size added in v0.2.0

func (r *Reader) Size() uint64

Size returns the current box's total size including header.

func (*Reader) Skip added in v0.2.0

func (r *Reader) Skip(n int)

Skip advances the data position by n bytes within the current container. Use after Enter to skip fixed-size headers before child boxes.

func (*Reader) Type added in v0.2.0

func (r *Reader) Type() BoxType

Type returns the current box's type.

func (*Reader) Version added in v0.2.0

func (r *Reader) Version() uint8

Version returns the version field for full boxes.

type ScanEntry added in v0.2.0

type ScanEntry struct {
	Type       BoxType
	Size       int64 // total box size including header
	Offset     int64 // byte offset from start of stream
	HeaderSize int   // header size (8 or 16 bytes)
}

ScanEntry represents a top-level box discovered by the Scanner.

func (ScanEntry) DataOffset added in v0.2.0

func (e ScanEntry) DataOffset() int64

DataOffset returns the byte offset where the box data begins (after the header). Use it with io.ReaderAt.ReadAt to read box data without seeking.

func (ScanEntry) DataSize added in v0.2.0

func (e ScanEntry) DataSize() int64

DataSize returns the size of the box data (excluding the header).

type Scanner added in v0.2.0

type Scanner struct {
	// contains filtered or unexported fields
}

Scanner reads top-level box headers from an io.ReadSeeker without loading box contents into memory. Use it to discover box positions and sizes, then selectively read only the boxes you need.

Typical usage:

f, _ := os.Open("video.mp4")
sc := mp4.NewScanner(f)
for sc.Next() {
    e := sc.Entry()
    if e.Type == mp4.TypeMoov {
        buf := make([]byte, e.DataSize())
        sc.ReadBody(buf)
        r := mp4.NewReader(buf)
        // parse moov contents...
    }
}
if err := sc.Err(); err != nil { ... }

func NewScanner added in v0.2.0

func NewScanner(rs io.ReadSeeker) Scanner

NewScanner creates a Scanner that reads box headers from rs.

func (*Scanner) Entry added in v0.2.0

func (s *Scanner) Entry() ScanEntry

Entry returns the current box entry. Only valid after Next returns true.

func (*Scanner) Err added in v0.2.0

func (s *Scanner) Err() error

Err returns the first non-EOF error encountered by the Scanner.

func (*Scanner) Next added in v0.2.0

func (s *Scanner) Next() bool

Next advances to the next top-level box. Returns false when there are no more boxes or an error occurs. Check Err() after the loop.

func (*Scanner) ReadBody added in v0.2.0

func (s *Scanner) ReadBody(buf []byte) error

ReadBody reads the current box's data (excluding header) into buf. buf must be exactly DataSize() bytes. The scanner seeks to the data position, reads, then seeks back so that subsequent Next calls work correctly.

func (*Scanner) ReadBox added in v0.2.0

func (s *Scanner) ReadBox(buf []byte) error

ReadBox reads the current box's full data (including header) into buf. buf must be exactly Size bytes.

func (*Scanner) Reset added in v0.2.0

func (s *Scanner) Reset(rs io.ReadSeeker)

Reset discards all state and prepares the Scanner to read from rs. It lets a single Scanner be reused for multiple streams without reallocating.

type SidxEntry added in v0.2.0

type SidxEntry struct {
	ReferenceType  bool   // false = media, true = sub-sidx
	ReferencedSize uint32 // size in bytes of the referenced material
	SubsegDuration uint32 // duration in timescale units
	StartsWithSAP  bool   // starts with a stream access point
	SAPType        uint8  // SAP type (1-6)
}

SidxEntry represents one reference in a sidx box.

type StscEntry added in v0.2.0

type StscEntry struct {
	FirstChunk          uint32
	SamplesPerChunk     uint32
	SampleDescriptionId uint32
}

StscEntry is a sample-to-chunk entry.

type StscIter added in v0.2.0

type StscIter struct {
	// contains filtered or unexported fields
}

StscIter iterates over stsc entries.

func NewStscIter added in v0.2.0

func NewStscIter(data []byte) StscIter

NewStscIter creates an iterator from stsc box data.

func (*StscIter) Count added in v0.2.0

func (it *StscIter) Count() uint32

Count returns the total number of entries.

func (*StscIter) Next added in v0.2.0

func (it *StscIter) Next() (StscEntry, bool)

Next returns the next entry. Returns false when done.

type StszIter added in v0.2.0

type StszIter struct {
	// contains filtered or unexported fields
}

StszIter iterates over sample sizes in an stsz box.

func NewStszIter added in v0.2.0

func NewStszIter(data []byte) StszIter

NewStszIter creates an iterator from stsz box data.

func (*StszIter) Count added in v0.2.0

func (it *StszIter) Count() uint32

Count returns the total number of samples.

func (*StszIter) Next added in v0.2.0

func (it *StszIter) Next() (uint32, bool)

Next returns the next sample size. Returns (0, false) when done.

type SttsEntry added in v0.2.0

type SttsEntry struct {
	Count    uint32
	Duration uint32
}

SttsEntry is a time-to-sample entry.

type SttsIter added in v0.2.0

type SttsIter struct {
	// contains filtered or unexported fields
}

SttsIter iterates over stts entries.

func NewSttsIter added in v0.2.0

func NewSttsIter(data []byte) SttsIter

NewSttsIter creates an iterator from stts box data.

func (*SttsIter) Count added in v0.2.0

func (it *SttsIter) Count() uint32

Count returns the total number of entries.

func (*SttsIter) Next added in v0.2.0

func (it *SttsIter) Next() (SttsEntry, bool)

Next returns the next entry. Returns false when done.

type TrunEntry

type TrunEntry struct {
	Duration              uint32
	Size                  uint32
	Flags                 uint32
	CompositionTimeOffset int32
}

TrunEntry is a track run sample entry.

type TrunIter added in v0.2.0

type TrunIter struct {
	// contains filtered or unexported fields
}

TrunIter iterates over trun entries.

func NewTrunIter added in v0.2.0

func NewTrunIter(data []byte, flags uint32) TrunIter

NewTrunIter creates an iterator from trun box data with the given flags.

func (*TrunIter) Count added in v0.2.0

func (it *TrunIter) Count() uint32

Count returns the total number of samples.

func (*TrunIter) DataOffset added in v0.2.0

func (it *TrunIter) DataOffset() int32

DataOffset returns the trun data offset.

func (*TrunIter) FirstSampleFlags added in v0.2.0

func (it *TrunIter) FirstSampleFlags() uint32

FirstSampleFlags returns the first sample flags, if present.

func (*TrunIter) Next added in v0.2.0

func (it *TrunIter) Next() (TrunEntry, bool)

Next returns the next sample entry. Returns false when done.

type Uint32Iter added in v0.2.0

type Uint32Iter struct {
	// contains filtered or unexported fields
}

Uint32Iter iterates over uint32 entries (stco, stss).

func NewUint32Iter added in v0.2.0

func NewUint32Iter(data []byte) Uint32Iter

NewUint32Iter creates an iterator from box data containing a count + uint32 entries.

func (*Uint32Iter) Count added in v0.2.0

func (it *Uint32Iter) Count() uint32

Count returns the total number of entries.

func (*Uint32Iter) Next added in v0.2.0

func (it *Uint32Iter) Next() (uint32, bool)

Next returns the next entry. Returns (0, false) when done.

type VisualSampleEntry

type VisualSampleEntry struct {
	DataReferenceIndex uint16
	Width              uint16
	Height             uint16
	HResolution        uint32 // 16.16 fixed point
	VResolution        uint32 // 16.16 fixed point
	FrameCount         uint16
	CompressorName     string
	Depth              uint16
	ChildOffset        int // byte offset within data where child boxes begin
}

VisualSampleEntry holds parsed fields from a visual sample entry (e.g. avc1).

func ReadVisualSampleEntry added in v0.2.0

func ReadVisualSampleEntry(data []byte) VisualSampleEntry

ReadVisualSampleEntry parses a visual sample entry from box data. Child boxes (e.g. avcC) start at ChildOffset within the data.

type Writer added in v0.2.0

type Writer struct {
	// contains filtered or unexported fields
}

Writer encodes ISOBMFF boxes into the provided buffer.

The buffer must be large enough to hold all written data; writes beyond the buffer boundary will panic.

Use Writer.StartBox and Writer.EndBox to write nested boxes:

w := mp4.NewWriter(buf)
w.StartBox(mp4.TypeMoov)
w.WriteMvhd(1000, 30000, 3)
w.EndBox()
output := w.Bytes()

After all writes, check Writer.Err for errors.

func NewWriter added in v0.2.0

func NewWriter(buf []byte) Writer

NewWriter creates a Writer that writes into buf.

func (*Writer) Bytes added in v0.2.0

func (w *Writer) Bytes() []byte

Bytes returns the written data.

func (*Writer) EndBox added in v0.2.0

func (w *Writer) EndBox()

EndBox finishes the current box by backpatching its size.

func (*Writer) Err added in v0.2.0

func (w *Writer) Err() error

Err returns the first deferred error encountered during writing.

func (*Writer) Len added in v0.2.0

func (w *Writer) Len() int

Len returns the number of bytes written.

func (*Writer) Reset added in v0.2.0

func (w *Writer) Reset()

Reset resets the writer position to 0 and clears any error state.

func (*Writer) StartBox added in v0.2.0

func (w *Writer) StartBox(t BoxType)

StartBox begins a new box. Write content, then call EndBox.

func (*Writer) StartFullBox added in v0.2.0

func (w *Writer) StartFullBox(t BoxType, version uint8, flags uint32)

StartFullBox begins a new full box with version and flags.

func (*Writer) Write added in v0.2.0

func (w *Writer) Write(p []byte) (int, error)

Write appends raw bytes. Implements io.Writer.

func (*Writer) WriteAudioSampleEntry added in v0.2.0

func (w *Writer) WriteAudioSampleEntry(dataRefIdx, channelCount, sampleSize uint16, sampleRate uint32)

WriteAudioSampleEntry writes the 28-byte audio sample entry header. The caller must start the box (e.g. mp4a) and end it after writing children.

func (*Writer) WriteCo64 added in v0.2.0

func (w *Writer) WriteCo64(entries []uint64)

WriteCo64 writes a complete co64 box.

func (*Writer) WriteCtts added in v0.2.0

func (w *Writer) WriteCtts(entries []CttsEntry)

WriteCtts writes a complete ctts box.

func (*Writer) WriteDref added in v0.2.0

func (w *Writer) WriteDref()

WriteDref writes a dref box with a single self-referencing url entry.

func (*Writer) WriteElst added in v0.2.0

func (w *Writer) WriteElst(entries []ElstEntry)

WriteElst writes a complete elst box.

func (*Writer) WriteFtyp added in v0.2.0

func (w *Writer) WriteFtyp(brand [4]byte, brandVersion uint32, compat [][4]byte)

WriteFtyp writes a complete ftyp box.

func (*Writer) WriteHdlr added in v0.2.0

func (w *Writer) WriteHdlr(handlerType [4]byte, name string)

WriteHdlr writes a complete hdlr box.

func (*Writer) WriteMdhd added in v0.2.0

func (w *Writer) WriteMdhd(timescale uint32, duration uint64, language uint16)

WriteMdhd writes a complete mdhd box.

func (*Writer) WriteMehd added in v0.2.0

func (w *Writer) WriteMehd(fragmentDuration uint64)

WriteMehd writes a complete mehd box.

func (*Writer) WriteMfhd added in v0.2.0

func (w *Writer) WriteMfhd(sequenceNumber uint32)

WriteMfhd writes a complete mfhd box.

func (*Writer) WriteMvhd added in v0.2.0

func (w *Writer) WriteMvhd(timescale uint32, duration uint64, nextTrackId uint32)

WriteMvhd writes a complete mvhd box.

func (*Writer) WriteSidx added in v0.2.0

func (w *Writer) WriteSidx(trackID uint32, timescale uint32, earliestPTS uint64, firstOffset uint64, entries []SidxEntry)

WriteSidx writes a segment index box (version 1, 64-bit times).

func (*Writer) WriteSmhd added in v0.2.0

func (w *Writer) WriteSmhd()

WriteSmhd writes a complete smhd box.

func (*Writer) WriteStco added in v0.2.0

func (w *Writer) WriteStco(entries []uint32)

WriteStco writes a complete stco box.

func (*Writer) WriteStsc added in v0.2.0

func (w *Writer) WriteStsc(entries []StscEntry)

WriteStsc writes a complete stsc box.

func (*Writer) WriteStss added in v0.2.0

func (w *Writer) WriteStss(entries []uint32)

WriteStss writes a complete stss box.

func (*Writer) WriteStsz added in v0.2.0

func (w *Writer) WriteStsz(sampleSize uint32, entries []uint32)

WriteStsz writes a complete stsz box from an iterator or raw entries.

func (*Writer) WriteStts added in v0.2.0

func (w *Writer) WriteStts(entries []SttsEntry)

WriteStts writes a complete stts box.

func (*Writer) WriteStyp added in v0.2.0

func (w *Writer) WriteStyp(brand [4]byte, brandVersion uint32, compat [][4]byte)

WriteStyp writes a segment type box (same format as ftyp).

func (*Writer) WriteTfdt added in v0.2.0

func (w *Writer) WriteTfdt(baseMediaDecodeTime uint64)

WriteTfdt writes a complete tfdt box.

func (*Writer) WriteTfhd added in v0.2.0

func (w *Writer) WriteTfhd(flags, trackId, defaultDuration, defaultSize, defaultFlags uint32)

WriteTfhd writes a complete tfhd box. WriteTfhd writes a track fragment header. Default sample duration, size, and flags are written when their corresponding flag bits are set.

func (*Writer) WriteTkhd added in v0.2.0

func (w *Writer) WriteTkhd(flags uint32, trackId uint32, duration uint64, width, height uint32)

WriteTkhd writes a complete tkhd box.

func (*Writer) WriteTrex added in v0.2.0

func (w *Writer) WriteTrex(trackId, descIdx, defDuration, defSize, defFlags uint32)

WriteTrex writes a complete trex box.

func (*Writer) WriteTrun added in v0.2.0

func (w *Writer) WriteTrun(flags uint32, dataOffset int32, firstSampleFlags uint32, entries []TrunEntry)

WriteTrun writes a complete trun box. WriteTrun writes a track run. firstSampleFlags is written when TrunFirstSampleFlagsPresent is set, overriding the default for sample one.

func (*Writer) WriteVisualSampleEntry added in v0.2.0

func (w *Writer) WriteVisualSampleEntry(dataRefIdx, width, height, frameCount, depth uint16, compressor string)

WriteVisualSampleEntry writes the 78-byte visual sample entry header. The caller must start the box (e.g. avc1) and end it after writing children.

func (*Writer) WriteVmhd added in v0.2.0

func (w *Writer) WriteVmhd()

WriteVmhd writes a complete vmhd box.

Directories

Path Synopsis
cmd
mp4dump command
Command mp4dump reads an MP4 file and prints its box structure.
Command mp4dump reads an MP4 file and prints its box structure.
mp4probe command
Command mp4probe displays information about MP4 tracks and keyframes.
Command mp4probe displays information about MP4 tracks and keyframes.
mp4remux command
Command mp4remux converts MP4 files to fragmented MP4 streams.
Command mp4remux converts MP4 files to fragmented MP4 streams.
Package fragment provides streaming MP4 fragmentation.
Package fragment provides streaming MP4 fragmentation.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL