Compare commits
1 Commits
v0.1.0-alp
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
13de03cd1c |
2
.gitignore
vendored
2
.gitignore
vendored
@@ -1 +1,3 @@
|
|||||||
*.png
|
*.png
|
||||||
|
*.webp
|
||||||
|
main
|
||||||
|
|||||||
@@ -14,6 +14,9 @@ var (
|
|||||||
intervalFlag = flag.Int("interval", 20, "Interval in seconds between thumbnails")
|
intervalFlag = flag.Int("interval", 20, "Interval in seconds between thumbnails")
|
||||||
maxThumbnailsFlag = flag.Int("max", 0, "Max Thumbnails, default as much as possible with interval")
|
maxThumbnailsFlag = flag.Int("max", 0, "Max Thumbnails, default as much as possible with interval")
|
||||||
blackFilterFlag = flag.Bool("filter", true, "Try to filter out black frames, might be an expensive operation")
|
blackFilterFlag = flag.Bool("filter", true, "Try to filter out black frames, might be an expensive operation")
|
||||||
|
formatFlag = flag.String("format", "png", "Output format")
|
||||||
|
segmentsFlag = flag.Bool("segments", false, "If active uses interval for how many segments are supposed to be done")
|
||||||
|
widthFlag = flag.Int("width", -1, "Set the width of the picture to scale to, -1 = max")
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
@@ -21,7 +24,15 @@ func main() {
|
|||||||
|
|
||||||
if *pathFlag != "" {
|
if *pathFlag != "" {
|
||||||
// thumbnails, num, err := thumbnailgen.GetThumbnail(*pathFlag, *intervalFlag, *maxThumbnailsFlag, *blackFilterFlag)
|
// thumbnails, num, err := thumbnailgen.GetThumbnail(*pathFlag, *intervalFlag, *maxThumbnailsFlag, *blackFilterFlag)
|
||||||
thumbnails, num, err := thumbnailgen.GetThumbnailSegments(*pathFlag, 12, *blackFilterFlag)
|
opts := thumbnailgen.NewDefaultOptions()
|
||||||
|
thumbnails, num, err := opts.Apply(func(o *thumbnailgen.Options) {
|
||||||
|
o.EnableFilter = *blackFilterFlag
|
||||||
|
o.Interval = *intervalFlag
|
||||||
|
o.Format = *formatFlag
|
||||||
|
o.UseSegments = *segmentsFlag
|
||||||
|
o.Segments = *intervalFlag
|
||||||
|
o.Scale = fmt.Sprintf("%d:-1", *widthFlag)
|
||||||
|
}).GetThumbnail(*pathFlag)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
@@ -30,7 +41,7 @@ func main() {
|
|||||||
|
|
||||||
name := filepath.Base(*pathFlag)
|
name := filepath.Base(*pathFlag)
|
||||||
for i, thumbnail := range thumbnails[:num] {
|
for i, thumbnail := range thumbnails[:num] {
|
||||||
err := os.WriteFile(fmt.Sprintf("%s-%d.png", name, i), thumbnail, 0600)
|
err := os.WriteFile(fmt.Sprintf("%s-%d.%s", name, i, *formatFlag), thumbnail, 0600)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|||||||
67
generator.go
67
generator.go
@@ -16,9 +16,39 @@ type TimeFilter struct {
|
|||||||
End float64
|
End float64
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetThumbnailSegments(path string, segments int, enableFilter bool) ([][]byte, int, error) {
|
type Options struct {
|
||||||
|
Interval int
|
||||||
|
Segments int
|
||||||
|
UseSegments bool
|
||||||
|
Format string
|
||||||
|
Scale string
|
||||||
|
EnableFilter bool
|
||||||
|
MaxThumbnails int
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewDefaultOptions() Options {
|
||||||
|
return Options{
|
||||||
|
Interval: 5,
|
||||||
|
Segments: 0,
|
||||||
|
UseSegments: false,
|
||||||
|
Format: "webp",
|
||||||
|
Scale: "-1:-1",
|
||||||
|
EnableFilter: true,
|
||||||
|
MaxThumbnails: 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (options *Options) Apply(opts ...func(*Options)) *Options {
|
||||||
|
for _, opt := range opts {
|
||||||
|
opt(options)
|
||||||
|
}
|
||||||
|
|
||||||
|
return options
|
||||||
|
}
|
||||||
|
|
||||||
|
func (opts *Options) GetThumbnail(path string) ([][]byte, int, error) {
|
||||||
var filters []TimeFilter
|
var filters []TimeFilter
|
||||||
if enableFilter {
|
if opts.EnableFilter {
|
||||||
f, err := GetFilter(path)
|
f, err := GetFilter(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, 0, err
|
return nil, 0, err
|
||||||
@@ -31,30 +61,17 @@ func GetThumbnailSegments(path string, segments int, enableFilter bool) ([][]byt
|
|||||||
return nil, 0, err
|
return nil, 0, err
|
||||||
}
|
}
|
||||||
|
|
||||||
interval := length / float64(segments)
|
var interval int
|
||||||
|
if opts.UseSegments {
|
||||||
return getThumbnailUnderlying(path, 0, filters, length, int(interval), enableFilter)
|
interval = int(length / float64(opts.Segments))
|
||||||
}
|
} else {
|
||||||
|
interval = opts.Interval
|
||||||
func GetThumbnail(path string, intervalSeconds int, maxThumbnails int, enableFilter bool) ([][]byte, int, error) {
|
|
||||||
var filters []TimeFilter
|
|
||||||
if enableFilter {
|
|
||||||
f, err := GetFilter(path)
|
|
||||||
if err != nil {
|
|
||||||
return nil, 0, err
|
|
||||||
}
|
|
||||||
filters = f
|
|
||||||
}
|
}
|
||||||
|
|
||||||
length, err := GetVideoLength(path)
|
return GetThumbnailUnderlying(path, opts.MaxThumbnails, filters, length, interval, opts.EnableFilter, opts.Format, opts.Scale)
|
||||||
if err != nil {
|
|
||||||
return nil, 0, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return getThumbnailUnderlying(path, maxThumbnails, filters, length, intervalSeconds, enableFilter)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func getThumbnailUnderlying(path string, maxThumbnails int, filters []TimeFilter, length float64, intervalSeconds int, enableFilter bool) ([][]byte, int, error) {
|
func GetThumbnailUnderlying(path string, maxThumbnails int, filters []TimeFilter, length float64, intervalSeconds int, enableFilter bool, format string, scale string) ([][]byte, int, error) {
|
||||||
buf := bytes.NewBuffer(nil)
|
buf := bytes.NewBuffer(nil)
|
||||||
framesExtracted := 0
|
framesExtracted := 0
|
||||||
|
|
||||||
@@ -78,7 +95,7 @@ func getThumbnailUnderlying(path string, maxThumbnails int, filters []TimeFilter
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
err := GetImage(buf, path, int(time), "png")
|
err := GetImage(buf, path, int(time), format, scale)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, 0, err
|
return nil, 0, err
|
||||||
}
|
}
|
||||||
@@ -110,10 +127,10 @@ func FrameLiesWithinFilter(time float64, filters []TimeFilter) (bool, float64) {
|
|||||||
return false, time
|
return false, time
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetImage(buf *bytes.Buffer, path string, timestamp int, format string) error {
|
func GetImage(buf *bytes.Buffer, path string, timestamp int, format string, scale string) error {
|
||||||
var t time.Time
|
var t time.Time
|
||||||
t = t.Add(time.Duration(timestamp) * time.Second)
|
t = t.Add(time.Duration(timestamp) * time.Second)
|
||||||
cmd := exec.Command("ffmpeg", "-ss", t.Format("15:04:05"), "-i", path, "-vframes", "1", "-c:v", format, "-f", "image2pipe", "-")
|
cmd := exec.Command("ffmpeg", "-ss", t.Format("15:04:05"), "-i", path, "-vframes", "1", "-c:v", format, "-filter:v", fmt.Sprintf("scale=%s", scale), "-f", "image2pipe", "-")
|
||||||
cmd.Stdout = buf
|
cmd.Stdout = buf
|
||||||
err := cmd.Run()
|
err := cmd.Run()
|
||||||
return err
|
return err
|
||||||
|
|||||||
Reference in New Issue
Block a user