Skip to content

Commit

Permalink
Merge pull request #55 from theckman/new_spinner_gifs
Browse files Browse the repository at this point in the history
Update README spinner gifs, add tooling + notes used to create them
  • Loading branch information
theckman committed Dec 30, 2021
2 parents c465bed + 928a05f commit 41ac194
Show file tree
Hide file tree
Showing 6 changed files with 295 additions and 83 deletions.
9 changes: 9 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,12 @@ coverage.txt

# Dependency directories (remove the comment below to include it)
# vendor/

# README GIF generation files
*.mov
*.mp4
*.gif
*.prproj

# OS files
.DS_Store
179 changes: 96 additions & 83 deletions README.md

Large diffs are not rendered by default.

44 changes: 44 additions & 0 deletions examples/demo/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# demo

This program is the helper used to create the gifs in the README. What follows
are notes for when I do this in the future.

### Overview

The software in this `demo` folder is used to demonstrate all of the spinners
that exist, and to help generate the GIFs used for the README.md file in the
root of this repo.

There are two helper scripts in the `scripts/` folder. `ffmpeg.sh` helps with
converting the h.264 .mp4 files into .gif files. The `rename.go` program then
helps rename those .gif files into the right name for committing to the
repository.

The GIFs are stored in a sister GitHub repository, [github.com/theckman/yacspin-gifs](https://github.com/theckman/yacspin-gifs)
to avoid cluttering up this repo with binary files (images).

#### Checklist

- [ ] start a screen recording of the terminal using Apple QuickTime Player
- [ ] start the demo program (`main.go`) and let it run entirely before stopping the QuickTime recording
- [ ] load the .mov file into Adobe Preimere, and cut the clip down into the individual 10 second clips of each spinner
- [ ] turn the clips in the original Sequence into Subsequences
- [ ] use media encoder to export those subsequences to their own files, matching source with Adaptive High Bitrate
- [ ] use the `scripts/ffmpeg.sh` script to convert the `.mp4` files into `.gif` files
- [ ] `go run` the `scripts/rename.go` program, to rename the `.gif` files to match the names we expect

#### QuickTime Capture Sizes

When using the Apple QuickTime Player to capture the screen recording, you can
have it only capture a specific area of the screen. These are the capture sizes
I played with on my Apple 16" M1 Max MBP laptop.

Please note, that the video files rendered from these captures tend to have
about 2x the resolution. Keep that in mind when deciding how large of an area
you want to capture.

Capture Size (pixels) | Font Size
----------------------|----------
650w x 24h | 18
340w x 12h | 10
1300w x 47h | 38
66 changes: 66 additions & 0 deletions examples/demo/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
// This program was used to generate the gifs in the README file

package main

import (
"fmt"
"os"
"os/signal"
"runtime"
"runtime/debug"
"syscall"
"time"

"github.com/theckman/yacspin"
)

func main() {
// disable GC
debug.SetGCPercent(-1)

cfg := yacspin.Config{
Frequency: 200 * time.Millisecond,
CharSet: yacspin.CharSets[36],
SuffixAutoColon: true,
Suffix: " example spinner",
Message: "initial message",
Colors: []string{"fgYellow"},
}

spinner, err := yacspin.New(cfg)
if err != nil {
fmt.Fprintf(os.Stderr, "failed to create spinner: %v\n", err)
os.Exit(1)
}

// handle SIGINT / SIGTERM without needing terminal reset
sigc := make(chan os.Signal, 2)
signal.Notify(sigc, syscall.SIGINT, syscall.SIGTERM)
go func() {
<-sigc
_ = spinner.Stop()
os.Exit(0)
}()

// run GC once before we start to render
runtime.GC()

time.Sleep(3 * time.Second)

for i := 0; i < len(yacspin.CharSets); i++ {
spinner.Message("initial message")

// interesting charsets for recording sizing: 19, 36
_ = spinner.CharSet(yacspin.CharSets[i])

_ = spinner.Start()

time.Sleep(5 * time.Second)

spinner.Message("updated message")

time.Sleep(5 * time.Second)

_ = spinner.Stop()
}
}
18 changes: 18 additions & 0 deletions examples/demo/scripts/ffmpeg.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#!/bin/bash

####
#
# Convert *.mp4 files in the current directory to GIFs at 10 FPS
#
####

function main() {
for file in *.mp4;
do
basename=$(echo "${file}" | sed -e 's/\.mp4$//')

ffmpeg -i "${basename}.mp4" -vf "fps=10,split[s0][s1];[s0]palettegen[p];[s1][p]paletteuse" -loop 0 "${basename}.gif"
done
}

main
62 changes: 62 additions & 0 deletions examples/demo/scripts/rename.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package main

import (
"flag"
"fmt"
"os"
"path/filepath"
"strconv"
"strings"
"syscall"
)

func main() {
var sim bool
var glob string

flag.BoolVar(&sim, "sim", false, "simulate")
flag.StringVar(&glob, "glob", "", "glob to use for matching files, must end in *.gif")
flag.Parse()

if !strings.HasSuffix(glob, "*.gif") {
fmt.Fprintln(os.Stderr, "-glob flag required and must end in *.gif")
os.Exit(int(syscall.EINVAL))
}

m, err := filepath.Glob(glob)
if err != nil {
fmt.Fprintf(os.Stderr, "failed to glob %s: %v\n", glob, err)
os.Exit(1)
}

if len(m) == 0 {
fmt.Fprintf(os.Stderr, "no files matched glob %s\n", glob)
os.Exit(1)
}

idx := strings.Index(glob, "*")

for _, match := range m {
num := strings.TrimSuffix(match[idx:], ".gif")

ni, err := strconv.Atoi(num)
if err != nil {
fmt.Fprintf(os.Stderr, "failed to convert number in %s to integer: %v\n", match, err)
os.Exit(1)
}

ni--

newName := fmt.Sprintf("%d.gif", ni)

if sim {
fmt.Printf("would rename %s to %s\n", match, newName)
continue
}

if err := os.Rename(match, newName); err != nil {
fmt.Fprintf(os.Stderr, "failed to rename %s to %s\n", match, newName)
os.Exit(1)
}
}
}

0 comments on commit 41ac194

Please sign in to comment.