filter using ffmpeg on linux with rembg

This commit is contained in:
talksik
2026-01-20 18:09:07 -08:00
commit ea0f22a2ca
5 changed files with 158 additions and 0 deletions
+50
View File
@@ -0,0 +1,50 @@
# Photo Background Remover
A simple Go program that captures a photo from your webcam and removes the background.
## Prerequisites
### 1. Install ffmpeg
```bash
# Ubuntu/Debian
sudo apt install ffmpeg
# macOS
brew install ffmpeg
```
### 2. Install Docker
```bash
# Ubuntu/Debian
sudo apt install docker.io
# macOS
brew install --cask docker
```
The program uses the `danielgatis/rembg` Docker container for background removal. The AI model (~176MB) will be downloaded automatically on first run.
## Usage
1. Build and run the program:
```bash
go run main.go
```
2. The program will:
- Capture a photo from your webcam
- Remove the background
- Save both images in the `output/` directory
## Output
- `output/photo_TIMESTAMP.jpg` - Original photo
- `output/photo_TIMESTAMP_nobg.png` - Photo with background removed
## Troubleshooting
- **Webcam not found**: Make sure `/dev/video0` exists (Linux) or adjust the device in the code
- **ffmpeg not found**: Install ffmpeg using the commands above
- **Docker not found**: Install Docker using the commands above
- **Docker permission denied**: Add your user to the docker group: `sudo usermod -a -G docker $USER` (then log out and back in)
- **Webcam permission denied**: You may need to add your user to the `video` group: `sudo usermod -a -G video $USER`
+3
View File
@@ -0,0 +1,3 @@
module video-filter
go 1.25.2
+105
View File
@@ -0,0 +1,105 @@
package main
import (
"fmt"
"os"
"os/exec"
"path/filepath"
"time"
)
func main() {
// Create output directory if it doesn't exist
outputDir := "output"
if err := os.MkdirAll(outputDir, 0755); err != nil {
fmt.Printf("Error creating output directory: %v\n", err)
os.Exit(1)
}
// Generate filenames with timestamp
timestamp := time.Now().Format("20060102_150405")
originalPhoto := filepath.Join(outputDir, fmt.Sprintf("photo_%s.jpg", timestamp))
processedPhoto := filepath.Join(outputDir, fmt.Sprintf("photo_%s_nobg.png", timestamp))
fmt.Println("📸 Capturing photo from webcam...")
if err := capturePhoto(originalPhoto); err != nil {
fmt.Printf("Error capturing photo: %v\n", err)
os.Exit(1)
}
fmt.Printf("✓ Photo saved to: %s\n", originalPhoto)
fmt.Println("🎨 Removing background...")
if err := removeBackground(originalPhoto, processedPhoto); err != nil {
fmt.Printf("Error removing background: %v\n", err)
os.Exit(1)
}
fmt.Printf("✓ Processed photo saved to: %s\n", processedPhoto)
fmt.Println("\n🎉 Done! Background removed successfully!")
}
// capturePhoto captures a single frame from the webcam using ffmpeg
func capturePhoto(outputPath string) error {
// For Linux, typically /dev/video0
// For macOS, use "0:0" with avfoundation
// For Windows, use "video=CAMERA_NAME" with dshow
var cmd *exec.Cmd
// Detect platform and use appropriate video device
if _, err := os.Stat("/dev/video0"); err == nil {
// Linux
cmd = exec.Command("ffmpeg",
"-f", "v4l2",
"-i", "/dev/video0",
"-frames:v", "1",
"-y",
outputPath,
)
} else {
// Try macOS
cmd = exec.Command("ffmpeg",
"-f", "avfoundation",
"-i", "0",
"-frames:v", "1",
"-y",
outputPath,
)
}
output, err := cmd.CombinedOutput()
if err != nil {
return fmt.Errorf("ffmpeg error: %v\nOutput: %s", err, string(output))
}
return nil
}
// removeBackground removes the background using rembg Docker container
func removeBackground(inputPath, outputPath string) error {
// Get absolute path of current directory
cwd, err := os.Getwd()
if err != nil {
return fmt.Errorf("failed to get working directory: %v", err)
}
// Docker paths are relative to /data mount point
dockerInput := "/data/" + inputPath
dockerOutput := "/data/" + outputPath
// Use rembg Docker container
cmd := exec.Command("docker", "run", "--rm",
"-v", fmt.Sprintf("%s:/data", cwd),
"danielgatis/rembg",
"i",
dockerInput,
dockerOutput,
)
output, err := cmd.CombinedOutput()
if err != nil {
return fmt.Errorf("docker/rembg error: %v\nOutput: %s", err, string(output))
}
return nil
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 220 KiB