func (p *Publisher) WritePacket(pkt av.Packet) error {
	return p.WriteExtendedPacket(ExtendedPacket{Packet: pkt})
}
WritePacket publishes a single packet
package hls
import (
	"errors"
	"fmt"
	"strconv"
	"sync"
	"sync/atomic"
	"time"
	"eaglesong.dev/hls/internal/codectag"
	"eaglesong.dev/hls/internal/dashmpd"
	"eaglesong.dev/hls/internal/fmp4"
	"eaglesong.dev/hls/internal/fragment"
	"eaglesong.dev/hls/internal/ratedetect"
	"eaglesong.dev/hls/internal/segment"
	"eaglesong.dev/hls/internal/tsfrag"
	"github.com/nareix/joy4/av"
)
const (
	defaultFragmentLength = 200 * time.Millisecond
	slopOffset            = time.Millisecond
)
type Mode int
const (
	ModeSingleTrack Mode = iota
	ModeSeparateTracks
	ModeSingleAndSeparate
)
type Publisher struct {
	Mode Mode
	InitialDuration time.Duration
	BufferLength time.Duration
	FragmentLength time.Duration
	WorkDir string
	Prefetch bool
	pid     string  
	streams []av.CodecData
	tracks  []*track
	combo   *track
	primary *track       
	comboID int          
	vidx    int          
	baseMSN segment.MSN  
	baseDCN int   
	nextDCN bool  
	state   atomic.Value
	rate    ratedetect.Detector
	mpd     dashmpd.MPD
	mpdsnap atomic.Value
	subsMu sync.Mutex
	subs   subMap
	Precreate int
}
type track struct {
	segments []*segment.Segment
	frag     fragment.Fragmenter
	hdr      fragment.Header
	codecTag string
}
func (p *Publisher) WriteHeader(streams []av.CodecData) error {
	if len(streams) > 9 {
		return errors.New("too many streams")
	}
	p.pid = strconv.FormatInt(time.Now().Unix(), 36)
	p.streams = streams
	p.comboID = -1
	for i, cd := range streams {
		if cd.Type().IsVideo() {
			p.vidx = i
		}
	}
	if p.Mode != ModeSingleTrack {
		for i, cd := range streams {
			frag, err := fmp4.NewTrack(cd)
			if err != nil {
				return fmt.Errorf("stream %d: %w", i, err)
			}
			tag, err := codectag.Tag(cd)
			if err != nil {
				return fmt.Errorf("stream %d: %w", i, err)
			}
			t := &track{
				frag:     frag,
				hdr:      frag.Header(),
				codecTag: tag,
			}
			p.tracks = append(p.tracks, t)
			if i == p.vidx {
				p.primary = t
			}
		}
		p.initMPD()
	}
	if p.Mode != ModeSeparateTracks {
		var cfrag fragment.Fragmenter
		var err error
		if p.Mode == ModeSingleAndSeparate {
			cfrag, err = tsfrag.New(streams)
		} else {
			cfrag, err = fmp4.NewMovie(streams)
		}
		if err != nil {
			return fmt.Errorf("combined: %w", err)
		}
		t := &track{frag: cfrag, hdr: cfrag.Header()}
		p.comboID = len(p.tracks)
		p.tracks = append(p.tracks, t)
		p.combo = t
		p.primary = t
	}
	return nil
}
func (p *Publisher) WriteTrailer() error {
	return nil
}
type ExtendedPacket struct {
	av.Packet
	ProgramTime time.Time
}