golang library for mux and demux file containers such as mpeg-ts,mpeg-ps,flv

gomedia

mpeg-ts,mpeg-ps,flv muxer/demuxer

  • mpeg-ts muxer

  • mpeg-ts demuxer

  • mpeg-ps muxer

  • mpeg-ps demuxer

  • flv muxer

  • flv demuxer

    mpeg-ps will be done in the next two weeks

Comments
  • example request:  progressive mp4 stream to mepg-ts  hls

    example request: progressive mp4 stream to mepg-ts hls

    progressive.mp4 is a mp4 file on local disk or nfs mount. hls player try to play this file with hls protocol.

    example server will read mp4, generate m3u8 and stream it in mpeg-ts format. reference https://www.jianshu.com/p/5eb817ccdd1f

  • ts转为mp4无法成功, 这段代码有什么问题呢 ?

    ts转为mp4无法成功, 这段代码有什么问题呢 ?

    package main
    
    import (
    	"fmt"
    	"io/ioutil"
    	"os"
    
    	"github.com/yapingcat/gomedia/mpeg2"
    	"github.com/yapingcat/gomedia/mp4"
    	"strconv"
    )
    
    type mymp4writer struct {
    	fp *os.File
    }
    
    func newmymp4writer(f *os.File) *mymp4writer {
    	return &mymp4writer{
    		fp: f,
    	}
    }
    
    func (mp4w *mymp4writer) Write(p []byte) (n int, err error) {
    	return mp4w.fp.Write(p)
    }
    func (mp4w *mymp4writer) Seek(offset int64, whence int) (int64, error) {
    	return mp4w.fp.Seek(offset, whence)
    }
    func (mp4w *mymp4writer) Tell() (offset int64) {
    	offset, _ = mp4w.fp.Seek(0, 1)
    	return
    }
    
    func main() {
    	tsfile := `/tmp/d/00002.ts`	// input
    	mp4filename := "test3.mp4"	// output
    	mp4file, err := os.OpenFile(mp4filename, os.O_CREATE|os.O_RDWR, 0666)
    	if err != nil {
    		fmt.Println(err)
    		return
    	}
    	defer mp4file.Close()
    
    	muxer := mp4.CreateMp4Muxer(newmymp4writer(mp4file))
    	vtid := muxer.AddVideoTrack(mp4.MP4_CODEC_H264)
    	atid := muxer.AddAudioTrack(mp4.MP4_CODEC_AAC, 0, 16, 44100)
    
    	buf, err := ioutil.ReadFile(tsfile)
    	if err != nil {
    		panic(err)
    	}
    	fmt.Printf("read %d size\n", len(buf))
    
    	demuxer := mpeg2.NewTSDemuxer()
    	demuxer.OnFrame = func(cid mpeg2.TS_STREAM_TYPE, frame []byte, pts uint64, dts uint64) {
    		if cid == mpeg2.TS_STREAM_AAC {
    			err = muxer.Write(atid, frame, uint64(pts), uint64(dts))
    			if err != nil {
    				panic(err)
    			}
    		} else if cid == mpeg2.TS_STREAM_H264 {
    			err = muxer.Write(vtid, frame, uint64(pts), uint64(dts))
    			if err != nil {
    				panic(err)
    			}
    		} else {
    			panic("unkwon cid " + strconv.Itoa(int(cid)))
    		}
    	}
    	err = demuxer.Input(buf)
    	if err != nil {
    		panic(err)
    	}
    	demuxer.Flush()
    
    	err = muxer.Writetrailer()
    	if err != nil {
    		panic(err)
    	}
    }
    
    
  • 从外部引入包, 编译失败

    从外部引入包, 编译失败

    好奇怪一个问题, 从外面引入这个包, 包中代码和git main 分支不一致,导致编译不过 ❯ go mod init aabbcc go: creating new go.mod: module aabbcc ❯ cp -r ~/git/golang/gomedia/example/example_play_mp4_with_hls.go ./ ❯ go mod tidy go: finding module for package github.com/yapingcat/gomedia/mpeg2 go: finding module for package github.com/yapingcat/gomedia/mp4 go: found github.com/yapingcat/gomedia/mp4 in github.com/yapingcat/gomedia/mp4 v0.0.0-20220617074658-94762898dc25 go: found github.com/yapingcat/gomedia/mpeg2 in github.com/yapingcat/gomedia/mpeg2 v0.0.0-20220617074658-94762898dc25 ❯ go build

    aabbcc

    ./example_play_mp4_with_hls.go:65:51: undefined: mp4.SyncSample ./example_play_mp4_with_hls.go:121:17: info.EndDts undefined (type mp4.TrackInfo has no field or method EndDts) ./example_play_mp4_with_hls.go:124:24: demuxer.GetSyncTable undefined (type *mp4.MovDemuxer has no field or method GetSyncTable) ./example_play_mp4_with_hls.go:158:10: demuxer.SeekTime undefined (type *mp4.MovDemuxer has no field or method SeekTime)

  • mp4muxer  Writetrailer() error

    mp4muxer Writetrailer() error

    muxer.Writetrailer() 后包报错, stbl-box.go中copy时未判断切片边界 panic: runtime error: slice bounds out of range [9229:9185]

    goroutine 656 [running]: github.com/yapingcat/gomedia/mp4.makeStblBox(0xc00018d800) /home/lnct/go/pkg/mod/github.com/yapingcat/gomedia/[email protected]/stbl-box.go:39 +0x4f8 github.com/yapingcat/gomedia/mp4.makeMinfBox(0xc00018d800) /home/lnct/go/pkg/mod/github.com/yapingcat/gomedia/[email protected]/minf-box.go:20 +0x7e github.com/yapingcat/gomedia/mp4.makeMdiaBox(0xc00018d800) /home/lnct/go/pkg/mod/github.com/yapingcat/gomedia/[email protected]/mdia-box.go:6 +0xdc github.com/yapingcat/gomedia/mp4.makeTrak(0x15e7800000002) /home/lnct/go/pkg/mod/github.com/yapingcat/gomedia/[email protected]/trak-box.go:7 +0x59 github.com/yapingcat/gomedia/mp4.(*Movmuxer).Writetrailer(0xc000311320) /home/lnct/go/pkg/mod/github.com/yapingcat/gomedia/[email protected]/mp4muxer.go:337 +0x39f

  • flv转mp4报错?

    flv转mp4报错?

    用的你的例程。 ` package main

    import ( "fmt" "os"

    "github.com/yapingcat/gomedia/go-codec"
    "github.com/yapingcat/gomedia/go-flv"
    "github.com/yapingcat/gomedia/go-mp4"
    

    )

    func FlvToMp4(Mp4FilePath, FlvFilePath string) { mp4file, err := os.OpenFile(Mp4FilePath, os.O_CREATE|os.O_RDWR, 0666) if err != nil { fmt.Println(err) return } defer mp4file.Close()

    muxer, err := mp4.CreateMp4Muxer(mp4file)
    if err != nil {
    	fmt.Println(err)
    	return
    }
    vtid := muxer.AddVideoTrack(mp4.MP4_CODEC_H264)
    atid := muxer.AddAudioTrack(mp4.MP4_CODEC_AAC)
    
    flvfilereader, _ := os.Open(FlvFilePath)
    defer flvfilereader.Close()
    fr := flv.CreateFlvReader()
    
    fr.OnFrame = func(cid codec.CodecID, b []byte, pts, dts uint32) {
    	if cid == codec.CODECID_AUDIO_AAC {
    		err := muxer.Write(atid, b, uint64(pts), uint64(dts))
    		if err != nil {
    			fmt.Println(err)
    		}
    
    	} else if cid == codec.CODECID_VIDEO_H264 {
    		err := muxer.Write(vtid, b, uint64(pts), uint64(dts))
    		if err != nil {
    			fmt.Println(err)
    		}
    	}
    }
    
    cache := make([]byte, 4096)
    for {
    	n, err := flvfilereader.Read(cache)
    	if err != nil {
    		fmt.Println(err)
    		break
    	}
    	fr.Input(cache[0:n])
    }
    err = muxer.WriteTrailer()
    if err != nil {
    	fmt.Println(err)
    }
    fmt.Println("flv转mp4完成!")
    

    }

    func main() { FlvToMp4("out.mp4", "out.flv") }

    `

    错误: ` EOF panic: runtime error: index out of range [0] with length 0

    goroutine 1 [running]: github.com/yapingcat/gomedia/go-mp4.(*mp4track).makeStblTable(0xc00008c8f0) D:/goproject/pkg/mod/github.com/yapingcat/[email protected]/go-mp4/mp4track.go:226 +0x552 github.com/yapingcat/gomedia/go-mp4.makeTrak(0xc00008c8f0, 0x1c060?) D:/goproject/pkg/mod/github.com/yapingcat/[email protected]/go-mp4/trak-box.go:9 +0x19a github.com/yapingcat/gomedia/go-mp4.(*Movmuxer).writeMoov(0xc0000d6000, {0xe87bc8, 0xc0000ce018}) D:/goproject/pkg/mod/github.com/yapingcat/[email protected]/go-mp4/mp4muxer.go:294 +0x1cb github.com/yapingcat/gomedia/go-mp4.(*Movmuxer).WriteTrailer(0xc0000d6000) D:/goproject/pkg/mod/github.com/yapingcat/[email protected]/go-mp4/mp4muxer.go:219 +0x17c main.FlvToMp4({0xe6005d?, 0x0?}, {0xe60056, 0x7}) D:/goproject/src/MoocDownload/test/3.go:64 +0x37a main.main() D:/goproject/src/MoocDownload/test/3.go:72 +0x2f `

    搞不懂为什么会出这样的错! 这个是视频链接: 链接:https://pan.baidu.com/s/1K4cl2kI6HSbKoSb_Fy32vg 提取码:lttl --来自百度网盘超级会员V3的分享

  • bug: if pps sps is not the first Frame , its pts shows wrong

    bug: if pps sps is not the first Frame , its pts shows wrong

    in https://github.com/yapingcat/gomedia/blob/main/example/example_demux_ts.go#L45 dump pts and dts

    if the pps and sps is not the first frame , its pts and dts present the last frame pts

    below is the first frame pts dts size type 2899 2899 17 7 sps 2899 2899 8 8 pps 2899 2899 1274 5 IDR 2899 2899 11899 5 2932 2932 7036 1

    below is not the first frame pts dts size type 22602 22602 24163 1 22635 22635 17621 1 22635 22635 17 7 sps 22635 22635 8 8 pps 62455 62455 1238 5 62455 62455 61365 5 62455 62455 3611 5 62489 62489 61424 1 in this case there is a gap in pts,
    the same issue exist when there is no gap

  • ps流文件转mp4报错,无法转换

    ps流文件转mp4报错,无法转换

    func main() { tsfile := "1666971231078.ps" tsFd, err := os.Open(tsfile) if err != nil { fmt.Println(err) return } defer tsFd.Close()

    hasAudio := false
    hasVideo := false
    var atid uint32 = 0
    var vtid uint32 = 0
    
    mp4filename := "convert_ps.mp4"
    mp4file, err := os.OpenFile(mp4filename, os.O_CREATE|os.O_RDWR, 0666)
    if err != nil {
    	fmt.Println(err)
    	return
    }
    defer mp4file.Close()
    
    muxer, err := mp4.CreateMp4Muxer(mp4file)
    if err != nil {
    	fmt.Println(err)
    	return
    }
    
    demuxer := mpeg2.NewPSDemuxer()
    //demuxer := mpeg2.NewTSDemuxer()
    demuxer.OnFrame = func(frame []byte, cid mpeg2.PS_STREAM_TYPE, pts uint64, dts uint64) {
    	if cid == mpeg2.PS_STREAM_H264 {
    		if !hasVideo {
    			vtid = muxer.AddVideoTrack(mp4.MP4_CODEC_H264)
    			hasVideo = true
    		}
    		err := muxer.Write(vtid, frame, uint64(pts), uint64(dts))
    		if err != nil {
    			fmt.Println(err)
    		}
    	} else if cid == mpeg2.PS_STREAM_AAC {
    		if !hasAudio {
    			atid = muxer.AddAudioTrack(mp4.MP4_CODEC_AAC)
    			hasAudio = true
    		}
    		err := muxer.Write(atid, frame, uint64(pts), uint64(dts))
    		if err != nil {
    			fmt.Println(err)
    		}
    	} else if cid == mpeg2.PS_STREAM_G711A {
    		if !hasAudio {
    			atid = muxer.AddAudioTrack(mp4.MP4_CODEC_G711A)
    			hasAudio = true
    		}
    		err := muxer.Write(atid, frame, uint64(pts), uint64(dts))
    		if err != nil {
    			fmt.Println(err)
    		}
    	} else if cid == mpeg2.PS_STREAM_G711U {
    		if !hasAudio {
    			atid = muxer.AddAudioTrack(mp4.MP4_CODEC_G711U)
    			hasAudio = true
    		}
    		err := muxer.Write(atid, frame, uint64(pts), uint64(dts))
    		if err != nil {
    			fmt.Println(err)
    		}
    	}
    }
    demuxer.OnPacket = func(pkg mpeg2.Display, decodeResult error) {
    
    }
    buf, _ := ioutil.ReadAll(tsFd)
    fmt.Printf("read %d size\n", len(buf))
    fmt.Println(demuxer.Input(buf))
    err = muxer.WriteTrailer()
    if err != nil {
    	fmt.Errorf("err:%v", err)
    	return
    }
    

    } 执行到muxer.WriteTrailer() 报错 panic: runtime error: index out of range [308] with length 308

  • 合并ts为mp4,在播放器上播放,点击快进到某一个时间点,画面会卡住

    合并ts为mp4,在播放器上播放,点击快进到某一个时间点,画面会卡住

    • 代码
    package main
    
    import (
    	"bytes"
    	"github.com/orestonce/goffmpeg"
    	"github.com/yapingcat/gomedia/mp4"
    	"github.com/yapingcat/gomedia/mpeg2"
    	"io/ioutil"
    	"os"
    	"path/filepath"
    	"strconv"
    )
    
    func main() {
    	const dir = `D:\d`
    	var nameList []string
    	for idx := 0; idx < 20; idx++ {
    		nameList = append(nameList, filepath.Join(dir, "output"+strconv.Itoa(idx)+".ts"))
    	}
    	fPath, err := goffmpeg.SetupFfmpeg()
    	if err != nil {
    		panic(err)
    	}
    	err = goffmpeg.MergeMultiToSingleMp4(goffmpeg.MergeMultiToSingleMp4_Req{
    		FfmpegExePath: fPath,
    		TsFileList:    nameList,
    		OutputMp4:     filepath.Join(dir, "merge-ffmpeg.mp4"),
    		ProgressCh:    nil,
    	})
    	if err != nil {
    		panic(err)
    	}
    	err = MergeTsFileListToSingleMp4(MergeTsFileListToSingleMp4_Req{
    		TsFileList: nameList,
    		OutputMp4:  filepath.Join(dir, "merge-gomedia.mp4"),
    	})
    	if err != nil {
    		panic(err)
    	}
    }
    
    type mymp4writer struct {
    	fp *os.File
    }
    
    func newmymp4writer(f *os.File) *mymp4writer {
    	return &mymp4writer{
    		fp: f,
    	}
    }
    
    func (mp4w *mymp4writer) Write(p []byte) (n int, err error) {
    	return mp4w.fp.Write(p)
    }
    func (mp4w *mymp4writer) Seek(offset int64, whence int) (int64, error) {
    	return mp4w.fp.Seek(offset, whence)
    }
    func (mp4w *mymp4writer) Tell() (offset int64) {
    	offset, _ = mp4w.fp.Seek(0, 1)
    	return
    }
    
    type MergeTsFileListToSingleMp4_Req struct {
    	TsFileList []string
    	OutputMp4  string
    }
    
    func MergeTsFileListToSingleMp4(req MergeTsFileListToSingleMp4_Req) (err error) {
    	mp4file, err := os.OpenFile(req.OutputMp4, os.O_CREATE|os.O_RDWR|os.O_TRUNC, 0666)
    	if err != nil {
    		return err
    	}
    	defer mp4file.Close()
    
    	muxer := mp4.CreateMp4Muxer(newmymp4writer(mp4file))
    	vtid := muxer.AddVideoTrack(mp4.MP4_CODEC_H264)
    	atid := muxer.AddAudioTrack(mp4.MP4_CODEC_AAC, 0, 16, 44100)
    
    	demuxer := mpeg2.NewTSDemuxer()
    	demuxer.OnFrame = func(cid mpeg2.TS_STREAM_TYPE, frame []byte, pts uint64, dts uint64) {
    
    		if cid == mpeg2.TS_STREAM_AAC {
    			err = muxer.Write(atid, frame, uint64(pts), uint64(dts))
    			if err != nil {
    				panic(err)
    			}
    		} else if cid == mpeg2.TS_STREAM_H264 {
    			err = muxer.Write(vtid, frame, uint64(pts), uint64(dts))
    			if err != nil {
    				panic(err)
    			}
    		} else {
    			panic("unkwon cid " + strconv.Itoa(int(cid)))
    		}
    	}
    
    	for _, tsFile := range req.TsFileList {
    		var buf []byte
    		buf, err = ioutil.ReadFile(tsFile)
    		if err != nil {
    			return err
    		}
    		err = demuxer.Input(bytes.NewReader(buf))
    		if err != nil {
    			return err
    		}
    	}
    
    	err = muxer.WriteTrailer()
    	if err != nil {
    		return err
    	}
    	return err
    }
    
    
  • mov读取支持

    mov读取支持

    mov与mp4的box封装格式几乎相同,但试图使用mp4.CreateMp4Demuxer打开mov文件时会返回mp4 Parser error

    mov, _ := os.Open("test.mov")
    defer mov.Close()
    md := mp4.CreateMp4Demuxer(mov)
    if infos, err := md.ReadHead(); err != nil && err != io.EOF {
    	panic(err)
    }
    

    请问我遗漏了什么内容、或是当前的MovDemuxer暂不支持吗? mov文件是使用ffmpeg -i test.mp4 -c copy test.mov将任意mp4文件转封装后得到的

  • mp4: muxer auto detect chanelCount & sampleRate for aac

    mp4: muxer auto detect chanelCount & sampleRate for aac

    Hi, this is another change I made in my fork.
    It autodetects the channel count and sample rate for aac audio tracks when muxing mp4's, similar to how the video resolution is autodetected.

    It adds a generic AddTrack function without any options to the muxer. But I am not that happy with the name, it will likely break in the future if more arguments are needed.
    Another option would be to use a function for each codec, something like this:

    func (muxer *Movmuxer) AddH264Track() uint32
    func (muxer *Movmuxer) AddH265Track() uint32
    func (muxer *Movmuxer) AddAACTrack() uint32
    // not sure if the G711 codecs could also support no arguments functions with auto detection
    func (muxer *Movmuxer) AddG711ATrack(channelcount uint8, sampleBits uint8, sampleRate uint) uint32
    func (muxer *Movmuxer) AddG711UTrack(channelcount uint8, sampleBits uint8, sampleRate uint) uint32
    

    and use the more generic names for functions with all track options:

    func (muxer *Movmuxer) AddVideoTrack(cid MP4_CODEC_TYPE, width uint32, height uint32) uint32
    func (muxer *Movmuxer) AddAudioTrack(cid MP4_CODEC_TYPE, channelcount uint8, sampleBits uint8, sampleRate uint) uint32
    

    Whereby I am not sure whether manually setting the width & height will ever be useful or needed 😄 But it more clearly differentiates the auto config functions from the expert/technical functions. Let me know what you prefer I can change the PR accordingly.

  • mpeg2: use io.Reader for ts demuxer

    mpeg2: use io.Reader for ts demuxer

    Hi again :D this PR is similar to #8 but for the ts demuxer. With this, instead of a byte slice the ts demuxer reads from an io.Reader. This makes it possible to demux larger .ts files since they do not have to be loaded completely into memory.

    It also makes the Flush function private and automatically calls it at the end of Input so users do not have to think about it. Additionally, there was a nil dereference bug in Flush that was triggered when the ts file contained a pes private stream without any packets.

    The last commit https://github.com/yapingcat/gomedia/commit/6dbd0a46d3c3c5f3e0477c655f648d4c3040852a tries to fix some decode errors that were silently ignored. For pes_pkg.Decode I had to add a special case in ts-demuxer, because you added an error when the remaining ts packet data is smaller than the expected pes packet data with commit 5fbdc43. For the ts demuxer the short read is the normal behavior, but I did not want to remove the error in case the Decode function is used somewhere else. Maybe the error is needed for the ps demuxer? (I did not test that).

Related tags
🔥 Golang live stream lib/client/server. support RTMP/RTSP/HLS/HTTP[S]-FLV/HTTP-TS, H264/H265/AAC, relay, cluster, record, HTTP API/Notify, GOP cache. 官方文档见 https://pengrl.com/lal
🔥 Golang live stream lib/client/server. support RTMP/RTSP/HLS/HTTP[S]-FLV/HTTP-TS, H264/H265/AAC, relay, cluster, record, HTTP API/Notify, GOP cache. 官方文档见 https://pengrl.com/lal

lal是一个开源GoLang直播流媒体网络传输项目,包含三个主要组成部分: lalserver:流媒体转发服务器。类似于nginx-rtmp-module等应用,但支持更多的协议,提供更丰富的功能。lalserver简介 demo:一些小应用,比如推、拉流客户端,压测工具,流分析工具,调度示例程序等

Jan 1, 2023
A simple library to extract video and audio frames from media containers (based on libav).
A simple library to extract video and audio frames from media containers (based on libav).

Reisen A simple library to extract video and audio frames from media containers (based on libav, i.e. ffmpeg). Dependencies The library requires libav

Jan 2, 2023
lmmp3 is a little golang library that download a video from youtube, and convert it to a mp3 file using ffmpeg

lmmp3 lmmp3 is a function that download a video from youtube, and convert it to a mp3 file using ffmpeg You need to have installed ffmpeg in your syst

Aug 12, 2022
golang function that download a video from youtube, and convert it to a mp3 file using ffmpeg

echedwnmp3 echedwnmp3 is a function that download a video from youtube, and convert it to a mp3 file using ffmpeg example package main import(echedwn

Dec 7, 2021
SlideXtract - A tool to help extract slides from a video file.

SlideXtract A tool to help extract slides from a video file. Slides are output in the out folder. Features I didn't find any other piece of code that

Jul 3, 2022
golang library to read and write various subtitle formats

libgosubs Golang library to read and write subtitles in the following formats Advanced SubStation Alpha v4 SRT TTML v1.0 - This is based on the spec p

Sep 27, 2022
Parser and generator of M3U8-playlists for Apple HLS. Library for Go language. :cinema:

M3U8 This is the most complete opensource library for parsing and generating of M3U8 playlists used in HTTP Live Streaming (Apple HLS) for internet vi

Dec 20, 2022
RTSP 1.0 client and server library for the Go programming language

RTSP 1.0 client and server library for the Go programming language

Jan 3, 2023
Go4vl is Go library for working with the Video for Linux API (V4L2) natively, without any C bindings.

go4vl A Go library for working with the Video for Linux user API (V4L2). Gov4l hides all the complexities of working with V4L2 and exposes idiomatic G

Dec 23, 2022
Parse and generate m3u8 playlists for Apple HTTP Live Streaming (HLS) in Golang (ported from gem https://github.com/sethdeckard/m3u8)

go-m3u8 Golang package for m3u8 (ported m3u8 gem https://github.com/sethdeckard/m3u8) go-m3u8 provides easy generation and parsing of m3u8 playlists d

Nov 19, 2022
Package implement reading and writing popular playlist formats: PLS, ASX, M3U, XSPF and others.

go-playlist ⚠️ WARNING The API is not stable yet and can change. Package playlist implement reading and writing popular playlist formats: PLS, ASX, M3

Oct 14, 2021
ffcommander - An easy frontend to FFmpeg and Imagemagick to automatically process video and manipulate subtitles.

% FFCOMMANDER(1) ffcommander 2.39 % Mikael Hartzell (C) 2018 % 2021 Name ffcommander - An easy frontend to FFmpeg and Imagemagick to automatically pro

May 9, 2022
Golang bindings for FFmpeg

goav Golang binding for FFmpeg A comprehensive binding to the ffmpeg video/audio manipulation library. Usage import "github.com/giorgisio/goav/avforma

Dec 27, 2022
live video streaming server in golang
live video streaming server in golang

中文 Simple and efficient live broadcast server: Very simple to install and use; Pure Golang, high performance, and cross-platform; Supports commonly us

Jan 4, 2023
live streaming server in golang
live streaming server in golang

中文 Simple and efficient live broadcast server: Very simple to install and use; Pure Golang, high performance, and cross-platform; Supports commonly us

Nov 10, 2022
Video converter with golang

Requirements Debian-like system (ubuntu, mint, etc...) with apt package manager Golang >1.15 Command tool make (use sudo apt install make -y to instal

Sep 10, 2022
ffmpeg core for golang

go-ffmpeg-core ffmpeg core for golang 基于ffmpeg命令封装简单功能,因此运行环境需事先安装有ffmpeg命令。 ffmpeg官方下载地址: http://ffmpeg.org/download.html 1. 剥离视频文件的音频/视频 package mai

Nov 26, 2021
📽 MovieGo - Video Editing in Golang

?? MovieGo - Video Editing in Golang MovieGo is a Golang library for video editing. The library is designed for fast processing of routine tasks relat

Dec 26, 2022
Go bindings for libVLC and high-level media player interface
Go bindings for libVLC and high-level media player interface

Go bindings for libVLC 2.X/3.X/4.X and high-level media player interface. The package can be useful for adding multimedia capabilities to applications

Dec 31, 2022