From 72939c3be749c21fdf0ca32fb992c3bf3a52ce26 Mon Sep 17 00:00:00 2001 From: Dmitry Sergeev Date: Tue, 15 Sep 2026 19:16:15 +0300 Subject: [PATCH] text overlay x & y pos as params --- cmd/mxl-pattern/main.go | 24 ++++++++++++++++++++++-- internal/generator/text.go | 8 +++++--- 2 files changed, 27 insertions(+), 5 deletions(-) diff --git a/cmd/mxl-pattern/main.go b/cmd/mxl-pattern/main.go index 58691d9..de6a2b6 100644 --- a/cmd/mxl-pattern/main.go +++ b/cmd/mxl-pattern/main.go @@ -31,7 +31,10 @@ type appArgs struct { audioFlowDefFile string pattern string listPatterns bool - textOverlay string + + textOverlay string + overlayX int + overlayY int videoWidth uint videoHeight uint @@ -249,7 +252,11 @@ func flagSetAddFlags(fs *pflag.FlagSet, args *appArgs) { // Video pattern flags fs.StringVarP(&args.pattern, "pattern", "p", "bars", "Video pattern type") fs.BoolVar(&args.listPatterns, "list-patterns", false, "List video available video patterns and exit") + fs.StringVarP(&args.textOverlay, "text", "t", "", "Text overlay above video pattern") + fs.IntVar(&args.overlayX, "text-x", 0, "Text overlay X position in px") + fs.IntVar(&args.overlayY, "text-y", 0, "Text overlay Y position in px") + fs.UintVar(&args.videoWidth, "width", 1920, "Video pattern width") fs.UintVar(&args.videoHeight, "height", 1080, "Video pattern height") fs.StringVar(&args.videoFPS, "fps", "25", "Video pattern FPS") @@ -341,7 +348,20 @@ func main() { log.Fatalf("text overlay init failed: %v", err) } defer face.Close() - overlay, err = generator.NewTextOverlay(args.textOverlay, int(vi.width), int(vi.height), face) + if args.overlayX < 0 || + args.overlayX > int(vi.width) || + args.overlayY < 0 || + args.overlayY > int(vi.height) { + log.Fatalf("Overlay X/Y pos can't be negative or greater, than video width/height") + } + overlay, err = generator.NewTextOverlay( + args.textOverlay, + int(vi.width), + int(vi.height), + args.overlayX, + args.overlayY, + face, + ) if err != nil { log.Fatalf("text overlay init failed: %v", err) } diff --git a/internal/generator/text.go b/internal/generator/text.go index 04f4de4..ae8ebd7 100644 --- a/internal/generator/text.go +++ b/internal/generator/text.go @@ -48,7 +48,7 @@ func LoadFace(path string, size float64) (font.Face, error) { // NewTextOverlay rasterizes text (white, anti-aliased) onto a black backing // box, centered horizontally. Box width and x are multiples of 6 so the box // covers whole v210 blocks and the per-frame copy is word-aligned. -func NewTextOverlay(text string, frameW, frameH int, face font.Face) (*TextOverlay, error) { +func NewTextOverlay(text string, frameW, frameH, posX, posY int, face font.Face) (*TextOverlay, error) { if text == "" { return nil, fmt.Errorf("text: empty string") } @@ -89,10 +89,12 @@ func NewTextOverlay(text string, frameW, frameH int, face font.Face) (*TextOverl return nil, fmt.Errorf("text: box %dpx does not fit frame height %dpx", topMargin+h, frameH) } + // posX = ((frameW - w) / 2 / 6) * 6 + // posY = topMargin o := &TextOverlay{ frameW: frameW, - x: ((frameW - w) / 2 / 6) * 6, - y: topMargin, + x: posX, + y: posY, w: w, h: h, cov: make([]byte, w*h),