feat: FFmpeg GUI desktop application
Wails v2 + Vue3 + Go project with: - Encode/Remux/Subtitle burn with hardware acceleration - Real-time progress with ffmpeg stderr parsing (\r delimiter handling) - Task queue with cancel support - Per-task log viewer with color-coded output - Custom frameless window with resize support - Dark/light theme toggle - Hardware encoder detection (NVENC/QSV/AMF)
This commit is contained in:
@@ -0,0 +1,65 @@
|
||||
package media
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"ffmpeg-gui/internal/ffmpeg"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// StreamInfo holds information about a single stream.
|
||||
type StreamInfo struct {
|
||||
Index int `json:"index"`
|
||||
CodecType string `json:"codec_type"`
|
||||
CodecName string `json:"codec_name"`
|
||||
Width int `json:"width,omitempty"`
|
||||
Height int `json:"height,omitempty"`
|
||||
Duration string `json:"duration,omitempty"`
|
||||
BitRate string `json:"bit_rate,omitempty"`
|
||||
FPS string `json:"r_frame_rate,omitempty"`
|
||||
Language string `json:"tags>language,omitempty"`
|
||||
}
|
||||
|
||||
// FormatInfo holds container format information.
|
||||
type FormatInfo struct {
|
||||
Filename string `json:"filename"`
|
||||
Format string `json:"format_name"`
|
||||
Duration string `json:"duration,omitempty"`
|
||||
Size string `json:"size,omitempty"`
|
||||
BitRate string `json:"bit_rate,omitempty"`
|
||||
}
|
||||
|
||||
// MediaInfo is the top-level ffprobe result.
|
||||
type MediaInfo struct {
|
||||
Streams []StreamInfo `json:"streams"`
|
||||
Format FormatInfo `json:"format"`
|
||||
}
|
||||
|
||||
// GetInfo runs ffprobe and returns parsed media information.
|
||||
func GetInfo(exec *ffmpeg.Executor, inputFile string) (*MediaInfo, error) {
|
||||
out, err := exec.Probe(
|
||||
"-v", "quiet",
|
||||
"-print_format", "json",
|
||||
"-show_format",
|
||||
"-show_streams",
|
||||
inputFile,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("ffprobe: %w (output: %s)", err, out)
|
||||
}
|
||||
|
||||
var info MediaInfo
|
||||
if err := json.Unmarshal([]byte(out), &info); err != nil {
|
||||
return nil, fmt.Errorf("parse ffprobe json: %w", err)
|
||||
}
|
||||
return &info, nil
|
||||
}
|
||||
|
||||
// GetDurationSeconds returns the duration in seconds as a float64.
|
||||
func (mi *MediaInfo) GetDurationSeconds() float64 {
|
||||
if mi.Format.Duration == "" {
|
||||
return 0
|
||||
}
|
||||
var secs float64
|
||||
fmt.Sscanf(mi.Format.Duration, "%f", &secs)
|
||||
return secs
|
||||
}
|
||||
Reference in New Issue
Block a user