This project started (as so many do) with a message from my brother with 2 links. He was looking at printing some stuff for his kid, and asked the inevitable question:

“How much filament will this use, and how long will it take?”

And there were only 100 individual STL files to check. Sure, my slicer could give estimates, but opening each file, slicing it, and checking the stats was tedious and time-consuming.

If you’ve spent any amount of time around 3D printers, you already know the eternal struggle:
“How long is this going to take?”
“How much filament will this use?”
“Do I have enough left to print this without discovering sadness at 3 a.m.?”

So for this week’s Weekend Rec Build, I put together something I’ve wanted for a long time: a stand-alone, slicer-agnostic print estimator that can scan STL files directly and give you reasonably accurate numbers for filament length, filament mass, and print time. From the command line or a lightweight web interface.

The project lives here: https://github.com/Solo-Web-Works/3D-Print-Estimator

Why Build This?

A surprising amount of 3D printing workflow friction happens before slicing.

If you maintain a library of dozens (or hundreds) of STLs, the usual preview-slice-estimate loop becomes tedious fast. I wanted something that works like a “pre-slicer inspector” — a little utility I can drop into any folder (or drop it into a folder in my path) and instantly get meaningful estimates.

Being able to run python estimator.py and get a spreadsheet of everything in the directory is incredibly convenient.

How It Works

At its core, the estimator analyzes STL geometry directly, binary or ASCII, and computes:

  1. Volume
  2. Surface area
  3. Bounding box dimensions

All of that happens in read_stl() and accumulate_triangle_stats() in estimator.py, where the script walks every triangle in the mesh, updating bounds, area, and signed tetrahedral volume to get an accurate solid volume.

Once the raw geometry is known, the next step is turning that into actual printable material and time estimates. That logic lives in the estimate() function.

Here’s what the estimator computes:

1. Shell Volume

The surface area is multiplied by the shell thickness:

  • shell_thickness = settings.perimeter_count * settings.nozzle_diameter_mm
  • shell_volume = stats.surface_area_mm2 * shell_thickness

Is it perfect? No.
Is it “good enough for predicting if I have enough filament left on the spool?” Absolutely.

2. Infill Volume

Whatever remains after subtracting shell volume becomes the interior. That gets scaled by the infill percentage:

  • internal_volume = max(stats.volume_mm3 - shell_volume, 0.0)
  • infill_volume = internal_volume * settings.infill_density

3. Filament Usage

From the estimated extrusion volume, the script computes filament length and mass:

  • filament_cross_section = π * (diameter / 2)^2
  • filament_length = total_extrusion_volume / filament_cross_section
  • filament_mass = (total_extrusion_volume / 1000) * density

This is where your actual filament density pays off. PLA, PETG, ABS, and infused filaments all vary, so the config file lets you dial that in.

4. Time Estimate

Finally, the estimator uses three print speeds:

  • Perimeter speed
  • Infill speed
  • Travel speed

Actual slicers know more about retractions, acceleration, jerk, and optimization paths. This tool intentionally doesn’t. The goal is useful approximations, not G-code-level precision.

Still, the heuristic works surprisingly well.

Two Ways to Use It

1. Command Line Mode

As long as Python is on your system:

python estimator.py --config printer-config.json

It scans all .stl files in the folder and outputs CSV by default.

You can choose JSON or XLSX instead. The XLSX mode even builds formulas for totals and human-readable hour/minute formatting, all handled in build_workbook().

Spreadsheet output sample (formatting added after generation):

Totals row automatically generated

2. Web Interface Mode

Run:

python estimator.py --serve --port 5000

Open http://localhost:5000, upload an STL (or ZIP of STLs), and get a clean table of results. You can even offer downloads as CSV, JSON, or XLSX. Not by writing files, but by embedding them as data URIs for one-click downloading.

The web mode is entirely self-contained – no templates, no external static files – and uses a simple Flask-rendered HTML string defined as WEB_TEMPLATE in the script.

Web mode sample:

Configuration: Your Printer, Your Rules

Everything about your printer setup lives in printer-config.json, documented in the project’s README.md. These setting will typically mirror your slicer profile, but you can tweak them independently if you want to experiment with different speeds, layer heights, or infill percentages.

{  "layer_height_mm": 0.2,
  "nozzle_diameter_mm": 0.4,
  "perimeter_count": 2,
  "top_layers": 4,
  "bottom_layers": 4,
  "infill_density": 0.25,
  "perimeter_speed_mm_s": 40.0,
  "infill_speed_mm_s": 60.0,
  "travel_speed_mm_s": 120.0,
  "filament_diameter_mm": 1.75,
  "filament_density_g_cm3": 1.24,
  "travel_factor": 0.1
}

Change it to match your printer, material, or printing preferences, and the estimator updates automatically.

What This Isn’t

This tool is not trying to:

  • Replace your slicer
  • Predict print time down to the minute
  • Handle variable layer heights
  • Model retraction, coasting, acceleration, or machine-specific quirks

But it is aiming to answer:

  • “Do I have enough filament?”
  • “Ballpark, how long will these prints take?”
  • “Which of these STLs is going to be a weekend print and which is a coffee break?”

And that’s exactly the problem it solves.

Where It Goes Next

Future improvements I’m toying with:

  • Per-model config overrides
  • Optional real-world calibration (feed it a known model + real print time, adjust heuristics)
  • A nicer web UI (I’m not a designer!)
  • A batch “compare the cost of these print settings” mode

This is one of those projects that’s small enough to stay enjoyable, but deep enough to keep offering fun ideas.