-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathimage_probe.go
More file actions
96 lines (89 loc) · 2.09 KB
/
Copy pathimage_probe.go
File metadata and controls
96 lines (89 loc) · 2.09 KB
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
package ffimage
import (
"context"
"encoding/json"
"fmt"
"os/exec"
"strconv"
"strings"
)
func (i *Image) loadImageSize(c context.Context) error {
cmd := exec.CommandContext(
c,
"ffprobe",
"-v", "error",
"-select_streams", "v:0",
"-show_entries", "stream=width,height,nb_frames",
"-of", "json",
i.Path,
)
output, err := cmd.Output()
if err != nil {
if c.Err() != nil {
return c.Err()
}
if exitError, isExitError := err.(*exec.ExitError); isExitError {
if ffprobeOutput := strings.TrimSpace(string(exitError.Stderr)); ffprobeOutput != "" {
return fmt.Errorf("ffprobe output: %w: %s", err, ffprobeOutput)
}
}
return fmt.Errorf("ffprobe output: %w", err)
}
probe := struct {
Streams []struct {
Width int `json:"width"`
Height int `json:"height"`
NbFrames string `json:"nb_frames"`
} `json:"streams"`
}{}
if err := json.Unmarshal(output, &probe); err != nil {
return fmt.Errorf("decode ffprobe output: %w", err)
}
if len(probe.Streams) == 0 || probe.Streams[0].Width == 0 || probe.Streams[0].Height == 0 {
return fmt.Errorf("no valid stream found")
}
i.sourceWidth = probe.Streams[0].Width
i.sourceHeight = probe.Streams[0].Height
i.setWidthHeight(i.sourceWidth, i.sourceHeight)
frames, err := strconv.Atoi(probe.Streams[0].NbFrames)
if err == nil && frames > 0 {
i.frames = frames
i.singleFrame = frames == 1
return nil
}
i.singleFrame = hasSingleFrame(c, i.Path)
if err := c.Err(); err != nil {
return err
}
return nil
}
func hasSingleFrame(c context.Context, path string) bool {
cmd := exec.CommandContext(
c,
"ffmpeg",
"-v", "error",
"-nostats",
"-progress", "pipe:1",
"-i", path,
"-map", "0:v:0",
"-frames:v", "2",
"-f", "null",
"-",
)
output, err := cmd.Output()
if err != nil {
return false
}
frames := 0
for _, line := range strings.Split(string(output), "\n") {
value, found := strings.CutPrefix(strings.TrimSpace(line), "frame=")
if !found {
continue
}
count, err := strconv.Atoi(strings.TrimSpace(value))
if err == nil && count > frames {
frames = count
}
}
return frames == 1
}