mirror of
https://github.com/u2takey/ffmpeg-go.git
synced 2025-10-04 23:52:42 +08:00
and stream example
This commit is contained in:
155
examples/stream.go
Normal file
155
examples/stream.go
Normal file
@@ -0,0 +1,155 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"sync"
|
||||
|
||||
ffmpeg "github.com/u2takey/ffmpeg-go"
|
||||
)
|
||||
|
||||
var (
|
||||
InputFile = flag.String("in_filename", "./in1.mp4", "Input filename")
|
||||
OutputFile = flag.String("out_filename", "./out.mp4", "Input filename")
|
||||
Dream = flag.Bool("dream", false, "Use DeepDream frame processing (requires tensorflow)")
|
||||
)
|
||||
|
||||
// Buffer is a goroutine safe bytes.Buffer
|
||||
type Buffer struct {
|
||||
buffer bytes.Buffer
|
||||
mutex sync.Mutex
|
||||
}
|
||||
|
||||
func (s *Buffer) Write(p []byte) (n int, err error) {
|
||||
s.mutex.Lock()
|
||||
defer s.mutex.Unlock()
|
||||
return s.buffer.Write(p)
|
||||
}
|
||||
|
||||
func (s *Buffer) Read(p []byte) (n int, err error) {
|
||||
s.mutex.Lock()
|
||||
defer s.mutex.Unlock()
|
||||
return s.buffer.Read(p)
|
||||
}
|
||||
|
||||
func getVideoSize(fileName string) (int, int) {
|
||||
log.Println("Getting video size for", fileName)
|
||||
data, err := ffmpeg.Probe(fileName)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
log.Println("got video info", data)
|
||||
type VideoInfo struct {
|
||||
Streams []struct {
|
||||
CodecType string `json:"codec_type"`
|
||||
Width int
|
||||
Height int
|
||||
} `json:"streams"`
|
||||
}
|
||||
vInfo := &VideoInfo{}
|
||||
err = json.Unmarshal([]byte(data), vInfo)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
for _, s := range vInfo.Streams {
|
||||
if s.CodecType == "video" {
|
||||
return s.Width, s.Height
|
||||
}
|
||||
}
|
||||
return 0, 0
|
||||
}
|
||||
|
||||
func startFFmpegProcess1(infileName string, writer io.WriteCloser) <-chan error {
|
||||
log.Println("Starting ffmpeg process1")
|
||||
done := make(chan error)
|
||||
go func() {
|
||||
err := ffmpeg.Input(infileName).
|
||||
Output("pipe:",
|
||||
ffmpeg.KwArgs{
|
||||
"format": "rawvideo", "pix_fmt": "rgb24",
|
||||
}).
|
||||
WithOutput(writer).
|
||||
Run()
|
||||
log.Println("ffmpeg process1 done")
|
||||
_ = writer.Close()
|
||||
done <- err
|
||||
close(done)
|
||||
}()
|
||||
return done
|
||||
}
|
||||
|
||||
func startFFmpegProcess2(outfileName string, buf io.Reader, width, height int) <-chan error {
|
||||
log.Println("Starting ffmpeg process2")
|
||||
done := make(chan error)
|
||||
go func() {
|
||||
err := ffmpeg.Input("pipe:",
|
||||
ffmpeg.KwArgs{"format": "rawvideo",
|
||||
"pix_fmt": "rgb24", "s": fmt.Sprintf("%dx%d", width, height),
|
||||
}).
|
||||
Output(outfileName, ffmpeg.KwArgs{"pix_fmt": "yuv420p"}).
|
||||
OverWriteOutput().
|
||||
WithInput(buf).
|
||||
Run()
|
||||
log.Println("ffmpeg process2 done")
|
||||
done <- err
|
||||
close(done)
|
||||
}()
|
||||
return done
|
||||
}
|
||||
|
||||
func process(reader io.ReadCloser, writer io.WriteCloser, w, h int) {
|
||||
go func() {
|
||||
frameSize := w * h * 3
|
||||
buf := make([]byte, frameSize, frameSize)
|
||||
for {
|
||||
n, err := io.ReadFull(reader, buf)
|
||||
if n == 0 || err == io.EOF {
|
||||
_ = writer.Close()
|
||||
return
|
||||
} else if n != frameSize || err != nil {
|
||||
panic(fmt.Sprintf("read error: %d, %s", n, err))
|
||||
}
|
||||
for i := range buf {
|
||||
buf[i] = buf[i] / 3
|
||||
}
|
||||
n, err = writer.Write(buf)
|
||||
if n != frameSize || err != nil {
|
||||
panic(fmt.Sprintf("write error: %d, %s", n, err))
|
||||
}
|
||||
}
|
||||
}()
|
||||
return
|
||||
}
|
||||
|
||||
func run(inFile, outFile string) {
|
||||
w, h := getVideoSize(inFile)
|
||||
log.Println(w, h)
|
||||
|
||||
pr1, pw1 := io.Pipe()
|
||||
pr2, pw2 := io.Pipe()
|
||||
done1 := startFFmpegProcess1(inFile, pw1)
|
||||
process(pr1, pw2, w, h)
|
||||
done2 := startFFmpegProcess2(outFile, pr2, w, h)
|
||||
err := <-done1
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
err = <-done2
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
log.Println("Done")
|
||||
}
|
||||
|
||||
func main() {
|
||||
flag.Parse()
|
||||
if *Dream == true {
|
||||
fmt.Println("tensorflow mode not implemented, todo")
|
||||
return
|
||||
}
|
||||
run(*InputFile, *OutputFile)
|
||||
}
|
Reference in New Issue
Block a user