-
Notifications
You must be signed in to change notification settings - Fork 172
/
showProgress.go
107 lines (96 loc) · 2.05 KB
/
showProgress.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
package examples
import (
"encoding/json"
"fmt"
"log"
"math/rand"
"net"
"os"
"path"
"regexp"
"strconv"
"strings"
"time"
ffmpeg "github.com/u2takey/ffmpeg-go"
)
// ExampleShowProgress is an example of using the ffmpeg `-progress` option with a
// unix-domain socket to report progress
func ExampleShowProgress(inFileName, outFileName string) {
a, err := ffmpeg.Probe(inFileName)
if err != nil {
panic(err)
}
totalDuration, err := probeDuration(a)
if err != nil {
panic(err)
}
err = ffmpeg.Input(inFileName).
Output(outFileName, ffmpeg.KwArgs{"c:v": "libx264", "preset": "veryslow"}).
GlobalArgs("-progress", "unix://"+TempSock(totalDuration)).
OverWriteOutput().
Run()
if err != nil {
panic(err)
}
}
func TempSock(totalDuration float64) string {
// serve
rand.Seed(time.Now().Unix())
sockFileName := path.Join(os.TempDir(), fmt.Sprintf("%d_sock", rand.Int()))
l, err := net.Listen("unix", sockFileName)
if err != nil {
panic(err)
}
go func() {
re := regexp.MustCompile(`out_time_ms=(\d+)`)
fd, err := l.Accept()
if err != nil {
log.Fatal("accept error:", err)
}
buf := make([]byte, 16)
data := ""
progress := ""
for {
_, err := fd.Read(buf)
if err != nil {
return
}
data += string(buf)
a := re.FindAllStringSubmatch(data, -1)
cp := ""
if len(a) > 0 && len(a[len(a)-1]) > 0 {
c, _ := strconv.Atoi(a[len(a)-1][len(a[len(a)-1])-1])
cp = fmt.Sprintf("%.2f", float64(c)/totalDuration/1000000)
}
if strings.Contains(data, "progress=end") {
cp = "done"
}
if cp == "" {
cp = ".0"
}
if cp != progress {
progress = cp
fmt.Println("progress: ", progress)
}
}
}()
return sockFileName
}
type probeFormat struct {
Duration string `json:"duration"`
}
type probeData struct {
Format probeFormat `json:"format"`
}
func probeDuration(a string) (float64, error) {
pd := probeData{}
err := json.Unmarshal([]byte(a), &pd)
if err != nil {
return 0, err
}
f, err := strconv.ParseFloat(pd.Format.Duration, 64)
if err != nil {
return 0, err
}
return f, nil
}