feat: add button to print compiled ffmpeg command and exit

This commit is contained in:
2024-01-03 22:24:58 +02:00
parent 8db706c5da
commit 46b3ec95bd
6 changed files with 109 additions and 42 deletions
+44 -6
View File
@@ -4,11 +4,13 @@ import (
"fmt" "fmt"
"os" "os"
"path/filepath" "path/filepath"
"strings"
"github.com/charmbracelet/bubbles/progress" "github.com/charmbracelet/bubbles/progress"
"github.com/charmbracelet/bubbles/spinner" "github.com/charmbracelet/bubbles/spinner"
tea "github.com/charmbracelet/bubbletea" tea "github.com/charmbracelet/bubbletea"
"github.com/charmbracelet/lipgloss" "github.com/charmbracelet/lipgloss"
ffmpeg "github.com/u2takey/ffmpeg-go"
) )
type Screen int type Screen int
@@ -38,6 +40,7 @@ type model struct {
Config map[int]Config Config map[int]Config
FocusIndex int FocusIndex int
ParsedConfig ParsedConfig ParsedConfig ParsedConfig
DryRun bool
ErrQuit bool ErrQuit bool
ErrQuitMessage string ErrQuitMessage string
} }
@@ -99,7 +102,11 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
case "enter", " ": case "enter", " ":
// parse config and switch to main screen if we're focused on the start button // parse config and switch to main screen if we're focused on the start button
if m.FocusIndex == len(Configs) { if m.FocusIndex == len(Configs) {
return m, m.parseConfig return m, m.parseConfig(false)
}
// parse config, print it and exit
if m.FocusIndex == len(Configs)+1 {
return m, m.parseConfig(true)
} }
case "tab", "shift+tab", "up", "down": case "tab", "shift+tab", "up", "down":
if key == "up" || key == "shift+tab" { if key == "up" || key == "shift+tab" {
@@ -108,10 +115,10 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
m.FocusIndex++ m.FocusIndex++
} }
if m.FocusIndex >= len(Configs)+1 { if m.FocusIndex >= len(Configs)+2 {
m.FocusIndex = 0 m.FocusIndex = 0
} else if m.FocusIndex < 0 { } else if m.FocusIndex < 0 {
m.FocusIndex = len(Configs) m.FocusIndex = len(Configs) + 1
} }
case "left", "right": case "left", "right":
if cfg, ok := m.Config[m.FocusIndex]; ok { if cfg, ok := m.Config[m.FocusIndex]; ok {
@@ -130,6 +137,9 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
m.Config[m.FocusIndex] = cfg m.Config[m.FocusIndex] = cfg
} }
} }
case quitMsg:
m.Quitting = true
return m, tea.Quit
case parsedCfgMsg: case parsedCfgMsg:
m.Screen = Main m.Screen = Main
m.ParsedConfig = msg.parsedConfig m.ParsedConfig = msg.parsedConfig
@@ -141,6 +151,10 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
m.FileCount = msg.fileCount m.FileCount = msg.fileCount
m.Files = msg.files m.Files = msg.files
if m.DryRun {
return m, gracefullyQuit
}
return m, encodeVideo return m, encodeVideo
case encodeVideoMsg: case encodeVideoMsg:
m.CurrentFileName = filepath.Base(m.Files[len(m.Files)-1]) m.CurrentFileName = filepath.Base(m.Files[len(m.Files)-1])
@@ -160,7 +174,7 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
m.Files = m.Files[:len(m.Files)-1] m.Files = m.Files[:len(m.Files)-1]
if len(m.Files) == 0 { if len(m.Files) == 0 {
return m, m.gracefullyQuit return m, gracefullyQuit
} }
return m, encodeVideo return m, encodeVideo
@@ -217,9 +231,15 @@ func CfgScreenView(m model) string {
} }
if m.FocusIndex == len(Configs) { if m.FocusIndex == len(Configs) {
view += FocusedButton view += FocusedStartButton
} else { } else {
view += BlurredButton view += BlurredStartButton
}
if m.FocusIndex == len(Configs)+1 {
view += FocusedDryRunButton
} else {
view += BlurredDryRunButton
} }
view += "\n" view += "\n"
@@ -252,8 +272,26 @@ func MainScreenView(m model) string {
func (m model) View() string { func (m model) View() string {
if m.Quitting { if m.Quitting {
if m.DryRun {
fullFilePath := m.Files[len(m.Files)-1]
fileName := filepath.Base(fullFilePath)
extensionIndex := strings.LastIndex(fileName, ".")
extension := fileName[extensionIndex:]
newFullFilePath := "./test-out" + extension
cli := ffmpeg.Input(fullFilePath).Output(newFullFilePath, ffmpeg.KwArgs{
"c:v": m.ParsedConfig.VideoEncoder,
"crf": m.ParsedConfig.CRF,
"preset": m.ParsedConfig.Preset,
"c:a": m.ParsedConfig.AudioEncoder,
"b:a": "128k"}).
Compile()
return fmt.Sprintf("%s %s\n", checkmark, strings.Join(cli.Args, " "))
} else {
return fmt.Sprintf("%s %d/%d files encoded\n", checkmark, m.FileCount-len(m.Files), m.FileCount) return fmt.Sprintf("%s %d/%d files encoded\n", checkmark, m.FileCount-len(m.Files), m.FileCount)
} }
}
if m.ErrQuit { if m.ErrQuit {
return fmt.Sprintf("%s %s\n", x, m.ErrQuitMessage) return fmt.Sprintf("%s %s\n", x, m.ErrQuitMessage)
+8 -2
View File
@@ -66,7 +66,7 @@ func encodeVideo() tea.Msg {
type quitMsg struct{} type quitMsg struct{}
func (m model) gracefullyQuit() tea.Msg { func gracefullyQuit() tea.Msg {
return quitMsg{} return quitMsg{}
} }
@@ -78,9 +78,13 @@ func initCfg() tea.Msg {
type parsedCfgMsg struct { type parsedCfgMsg struct {
parsedConfig ParsedConfig parsedConfig ParsedConfig
dryRun bool
} }
func (m *model) parseConfig() tea.Msg { func (m *model) parseConfig(dryRun bool) tea.Cmd {
m.DryRun = dryRun
return func() tea.Msg {
vEncoder := find(m.Config, "Video Encoder") vEncoder := find(m.Config, "Video Encoder")
aEncoder := find(m.Config, "Audio Encoder") aEncoder := find(m.Config, "Audio Encoder")
preset := find(m.Config, "Preset (libx264 & libx265 only)") preset := find(m.Config, "Preset (libx264 & libx265 only)")
@@ -95,6 +99,8 @@ func (m *model) parseConfig() tea.Msg {
Preset: preset.Opts[preset.FocusedOption], Preset: preset.Opts[preset.FocusedOption],
CRF: crf.Opts[crf.FocusedOption], CRF: crf.Opts[crf.FocusedOption],
}, },
dryRun: dryRun,
}
} }
} }
+1 -1
View File
@@ -7,5 +7,5 @@ require (
github.com/charmbracelet/bubbletea v0.20.0 github.com/charmbracelet/bubbletea v0.20.0
github.com/charmbracelet/lipgloss v0.5.0 github.com/charmbracelet/lipgloss v0.5.0
github.com/gabriel-vasile/mimetype v1.4.0 github.com/gabriel-vasile/mimetype v1.4.0
github.com/u2takey/ffmpeg-go v0.4.1 github.com/u2takey/ffmpeg-go v0.5.0
) )
+2
View File
@@ -73,6 +73,8 @@ github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/u2takey/ffmpeg-go v0.4.1 h1:l5ClIwL3N2LaH1zF3xivb3kP2HW95eyG5xhHE1JdZ9Y= github.com/u2takey/ffmpeg-go v0.4.1 h1:l5ClIwL3N2LaH1zF3xivb3kP2HW95eyG5xhHE1JdZ9Y=
github.com/u2takey/ffmpeg-go v0.4.1/go.mod h1:ruZWkvC1FEiUNjmROowOAps3ZcWxEiOpFoHCvk97kGc= github.com/u2takey/ffmpeg-go v0.4.1/go.mod h1:ruZWkvC1FEiUNjmROowOAps3ZcWxEiOpFoHCvk97kGc=
github.com/u2takey/ffmpeg-go v0.5.0 h1:r7d86XuL7uLWJ5mzSeQ03uvjfIhiJYvsRAJFCW4uklU=
github.com/u2takey/ffmpeg-go v0.5.0/go.mod h1:ruZWkvC1FEiUNjmROowOAps3ZcWxEiOpFoHCvk97kGc=
github.com/u2takey/go-utils v0.3.1 h1:TaQTgmEZZeDHQFYfd+AdUT1cT4QJgJn/XVPELhHw4ys= github.com/u2takey/go-utils v0.3.1 h1:TaQTgmEZZeDHQFYfd+AdUT1cT4QJgJn/XVPELhHw4ys=
github.com/u2takey/go-utils v0.3.1/go.mod h1:6e+v5vEZ/6gu12w/DC2ixZdZtCrNokVxD0JUklcqdCs= github.com/u2takey/go-utils v0.3.1/go.mod h1:6e+v5vEZ/6gu12w/DC2ixZdZtCrNokVxD0JUklcqdCs=
gocv.io/x/gocv v0.25.0/go.mod h1:Rar2PS6DV+T4FL+PM535EImD/h13hGVaHhnCu1xarBs= gocv.io/x/gocv v0.25.0/go.mod h1:Rar2PS6DV+T4FL+PM535EImD/h13hGVaHhnCu1xarBs=
+5 -2
View File
@@ -79,8 +79,11 @@ func encode(fullFilePath string, fileName string, teaP *tea.Program, cfg ParsedC
} }
} }
err = ffmpeg.Input(fullFilePath). quotedFilePath := fmt.Sprintf("\"%s\"", fullFilePath)
Output(newFileFullPath, ffmpeg.KwArgs{ quotedNewFilePath := fmt.Sprintf("\"%s\"", newFileFullPath)
err = ffmpeg.Input(quotedFilePath).
Output(quotedNewFilePath, ffmpeg.KwArgs{
"c:v": cfg.VideoEncoder, "c:v": cfg.VideoEncoder,
"crf": cfg.CRF, "crf": cfg.CRF,
"preset": cfg.Preset, "preset": cfg.Preset,
+20 -2
View File
@@ -32,7 +32,7 @@ var (
FocusedOption = lipgloss.NewStyle(). FocusedOption = lipgloss.NewStyle().
Foreground(SecondaryColor) Foreground(SecondaryColor)
FocusedButton = lipgloss.NewStyle(). FocusedStartButton = lipgloss.NewStyle().
Border(lipgloss.NormalBorder()). Border(lipgloss.NormalBorder()).
BorderForeground(AccentColor). BorderForeground(AccentColor).
Foreground(AccentColor). Foreground(AccentColor).
@@ -41,7 +41,7 @@ var (
Align(lipgloss.Center). Align(lipgloss.Center).
Bold(true). Bold(true).
Render("Start Encoding!") Render("Start Encoding!")
BlurredButton = lipgloss.NewStyle(). BlurredStartButton = lipgloss.NewStyle().
Border(lipgloss.NormalBorder()). Border(lipgloss.NormalBorder()).
BorderForeground(PrimaryColor). BorderForeground(PrimaryColor).
Foreground(PrimaryColor). Foreground(PrimaryColor).
@@ -49,4 +49,22 @@ var (
Padding(0, 2). Padding(0, 2).
Align(lipgloss.Center). Align(lipgloss.Center).
Render("Start Encoding!") Render("Start Encoding!")
FocusedDryRunButton = lipgloss.NewStyle().
Border(lipgloss.NormalBorder()).
BorderForeground(AccentColor).
Foreground(AccentColor).
MarginTop(1).
Padding(0, 2).
Align(lipgloss.Center).
Bold(true).
Render("Print FFmpeg command and exit")
BlurredDryRunButton = lipgloss.NewStyle().
Border(lipgloss.NormalBorder()).
BorderForeground(PrimaryColor).
Foreground(PrimaryColor).
MarginTop(1).
Padding(0, 2).
Align(lipgloss.Center).
Render("Print FFmpeg command and exit")
) )