Last active
August 24, 2020 11:14
-
-
Save fabstu/68a627386b502d5b5fc01e8980365a2e to your computer and use it in GitHub Desktop.
Screenreader with go
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Package takes screenshots. | |
package main | |
import ( | |
"context" | |
"os" | |
"github.com/spf13/cobra" | |
) | |
// RootCMD creates a root command of a program. | |
func RootCMD() *cobra.Command { | |
cmd := &cobra.Command{ | |
Use: "screenreader", | |
Short: "takes screenshots periodically", | |
} | |
cfgFlags := registerFlags(cmd) | |
cmd.RunE = func(cmd *cobra.Command, args []string) (err error) { | |
cfg, err := cfgFlags.makeSettings() | |
if err != nil { | |
return | |
} | |
return cfg.loop(context.Background()) | |
} | |
cmd.SetOut(os.Stdout) | |
cmd.SetErr(os.Stderr) | |
cmd.AddCommand() | |
return cmd | |
} | |
func main() { | |
errorExitCode := 1 | |
if err := RootCMD().Execute(); err != nil { | |
// if !helper.ContainsDoNotPrintHelp(err) { | |
// fmt.Println(err) | |
// } | |
os.Exit(errorExitCode) | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"context" | |
"fmt" | |
"image" | |
"image/png" | |
"os" | |
"path/filepath" | |
"time" | |
scrn "github.com/kbinani/screenshot" | |
"github.com/spf13/cobra" | |
"k8s.io/klog/v2" | |
) | |
type settings struct { | |
framerate int | |
saveLocation string | |
} | |
type settingsFlags struct { | |
framerate *int | |
saveLocation *string | |
} | |
var errOutDirectory = fmt.Errorf("error: out must be directory") | |
func registerFlags(cmd *cobra.Command) *settingsFlags { | |
return &settingsFlags{ | |
framerate: cmd.Flags().Int("framerate", 24, "framerate to capture screenshots with"), | |
saveLocation: cmd.Flags().String("out", ".screenshots", "where to stores the screenshots"), | |
} | |
} | |
func (cfgFlags *settingsFlags) makeSettings() (cfg *settings, err error) { | |
s, err := os.Stat(*cfgFlags.saveLocation) | |
if err != nil { | |
return | |
} | |
if !s.IsDir() { | |
return nil, errOutDirectory | |
} | |
return &settings{ | |
framerate: *cfgFlags.framerate, | |
saveLocation: *cfgFlags.saveLocation, | |
}, nil | |
} | |
func (cfg settings) loop(ctx context.Context) (err error) { | |
durationBetweenScreenshots := time.Second / time.Duration(cfg.framerate) | |
klog.InfoS("starting screenshot capture loop", | |
"settings", fmt.Sprintf("%#v", cfg), | |
"duration between screenshots", durationBetweenScreenshots, | |
) | |
// get main screen bounds | |
bounds := scrn.GetDisplayBounds(0) | |
ticker := time.NewTicker(durationBetweenScreenshots) | |
defer func() { | |
ticker.Stop() | |
}() | |
ctx, cancel := context.WithCancel(ctx) | |
defer func() { | |
cancel() | |
}() | |
for x := 0; ; x++ { | |
n := x | |
waitingForTickStart := time.Now() | |
select { | |
case <-ctx.Done(): | |
return | |
case t := <-ticker.C: | |
go func() { | |
start := time.Now() | |
ssSettings := &screenShotSettings{ | |
outFile: filepath.Join( | |
cfg.saveLocation, | |
fmt.Sprintf("%05d.png", n), | |
), | |
bounds: bounds, | |
} | |
klog.InfoS("Making screenshot", | |
"n", n, | |
"time_waiting_to_tick", time.Since(waitingForTickStart), | |
"tick-at", t, | |
"screenshot_settings", fmt.Sprintf("%#v", ssSettings), | |
) | |
err := takeScreenshot(ssSettings) | |
if err != nil { | |
klog.ErrorS(err, "screenshot failed", | |
"n", n, | |
"screenshot_settings", ssSettings, | |
) | |
cancel() | |
return | |
} | |
klog.InfoS("screenshot done", | |
"n", n, | |
"duration", time.Since(start), | |
) | |
}() | |
} | |
} | |
} | |
type screenShotSettings struct { | |
outFile string | |
bounds image.Rectangle | |
} | |
func takeScreenshot(cfg *screenShotSettings) (err error) { | |
// Take screenshot | |
img, err := scrn.CaptureRect(cfg.bounds) | |
if err != nil { | |
return err | |
} | |
// Create output file | |
f, err := os.Create(cfg.outFile) | |
if err != nil { | |
return err | |
} | |
defer f.Close() | |
// Encode screenshot | |
err = png.Encode(f, img) | |
if err != nil { | |
return err | |
} | |
return nil | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment