package browser import ( "encoding/base64" "fmt" "os" "path/filepath" ) // CdpScreenshotOpts configura el screenshot. type CdpScreenshotOpts struct { // FullPage indica si capturar la pagina completa (scroll height) o solo el viewport. FullPage bool // Quality es la calidad JPEG (0-100). Solo aplica si Format es "jpeg". Por defecto 80. Quality int // Format es el formato de imagen: "png" o "jpeg". Por defecto "png". Format string } // CdpScreenshot captura un screenshot de la pagina actual y lo guarda en outputPath. // Usa Page.captureScreenshot del protocolo CDP. // outputPath debe tener extension .png o .jpg/.jpeg segun el formato elegido. func CdpScreenshot(c *CDPConn, outputPath string, opts CdpScreenshotOpts) error { if c == nil { return fmt.Errorf("cdp screenshot: conexion nula") } if opts.Format == "" { opts.Format = "png" } if opts.Quality == 0 && opts.Format == "jpeg" { opts.Quality = 80 } params := map[string]any{ "format": opts.Format, "captureBeyondViewport": opts.FullPage, } if opts.Format == "jpeg" { params["quality"] = opts.Quality } if opts.FullPage { // Expandir clip para capturar toda la pagina scrollHeight, err := CdpEvaluate(c, "document.documentElement.scrollHeight") if err == nil { params["clip"] = nil // dejar que Chrome capture todo _ = scrollHeight } } result, err := c.sendCDP("Page.captureScreenshot", params) if err != nil { return fmt.Errorf("cdp screenshot: %w", err) } dataStr, ok := result["data"].(string) if !ok { return fmt.Errorf("cdp screenshot: campo data ausente en respuesta") } imgData, err := base64.StdEncoding.DecodeString(dataStr) if err != nil { return fmt.Errorf("cdp screenshot: decodificar base64: %w", err) } // Crear directorio si no existe if err := os.MkdirAll(filepath.Dir(outputPath), 0755); err != nil { return fmt.Errorf("cdp screenshot: crear directorio: %w", err) } if err := os.WriteFile(outputPath, imgData, 0644); err != nil { return fmt.Errorf("cdp screenshot: guardar archivo: %w", err) } return nil }