跳到正文
DEV Community· Muhamad Revanza Rafif Hamdani·· 3 小時前AI 評分33

如何從一個素材資料夾建立 Adobe、Vecteezy 和 Dreamstime CSV

Building Adobe, Vecteezy and Dreamstime CSVs From One Folder of Assets

AI 導讀

make_metadata.py 可從同一個素材資料夾產生符合 Adobe Stock、Vecteezy 和 Dreamstime 格式的 CSV,避免手動建立標題列出錯。

正文

I still have the rejection email open in a tab from last March. I had generated a batch of 120 sticker assets, spent an evening building what I thought was a clean upload spreadsheet, pasted 120 rows into Adobe Stock, and got back a parse error before a single row was reviewed. The header was wrong. Not the content, not the keywords, the header. Five columns, and I had six. That one night is the reason I now generate my CSVs from a script instead of typing them.

If you sell stock art, stickers, or templates on more than one platform, you already know the problem: the same folder of files needs three completely different spreadsheets, and each platform checks the header before it checks anything else. Here is what actually works, learned the slow way.

The headers are the gate, so treat them like code

Adobe Stock wants a 5 column CSV. Vecteezy wants 4 columns. Dreamstime wants 15. All three reject a wrong header instantly, before any human or model looks at your work. There is no partial credit.

The mistake I kept making was building these by hand in a spreadsheet, then "just adding a column" for a note to myself. A spreadsheet is not a build artifact. It is a place where silent mistakes live. The fix was to stop treating metadata as a document and start treating it as output from a script that has the correct header hardcoded and refuses to write anything else.

My make_metadata.py takes one folder of assets and emits the exact header each platform demands:

python make_metadata.py ./my-assets --platform adobe      --out metadata.csv   --ext .jpg
python make_metadata.py ./my-assets --platform vecteezy   --out vecteezy.csv   --ext .jpg
python make_metadata.py ./my-assets --platform dreamstime --out dreamstime.csv --ext .jpg

One folder, three CSVs, and the header can never drift because it is not typed, it is fixed in the code. Without a titles file it falls back to a title-cased filename, which is fine for a first pass but you should replace it before submitting. Filenames are not keywords.

Double-posting is the fastest way to get flagged

This one cost me a scare early on. I re-ran a batch overnight, forgot I had already uploaded half of it, and ended up with duplicates sitting in a review queue. Duplicate submissions are exactly the kind of thing that makes a reviewer distrust the rest of your catalogue, and trust is the only thing a small seller account has.

The fix is dumb and it works: a ledger. upload_tracker.py is a plain file that remembers what has been posted.

python upload_tracker.py pending items.txt
python upload_tracker.py done "asset-001.jpg"
python upload_tracker.py status

Before any upload run, I check pending. Before I mark anything complete, I check status. A re-run now skips anything already marked done. It uses the standard library alone, no install, no database, nothing to break. The boring solution is the one you will actually keep using.

One folder layout, not a junk drawer

Once you have 40 or 50 products, the thing that kills you is not generation, it is not knowing where anything is. This is the layout the whole pipeline assumes:

project/
  assets/            raw output
  output/            ready-to-submit files + metadata.csv
  packs/             finished zips + covers
  research/          notes and sources
  scripts/           the tools

One rule I learned by breaking it: keep research/ forever. I deleted my notes once to "clean up" and then spent a week reconstructing decisions I had already made. Your scrape logs and notes are the raw material for next quarter's products.

The tiny server habits

The whole pipeline runs on 1 vCPU, 2 GB RAM, no GPU. That constraint shaped more of the design than any platform rule. Four habits make it survivable:

  • One process at a time. Never fan out image jobs in parallel on a single core, it does not help and it will OOM.
  • Call gc.collect() after each asset. Freeing memory between items is the difference between a stable loop and a crash at item 90.
  • Measure peak RSS, not average, with resource.getrusage(RUSAGE_SELF).ru_maxrss. Averages lie about ceilings.
  • One file per subprocess for heavy render steps, so memory actually returns to the OS.
  • Render at the resolution you need. Inspecting a preview at 60 dpi instead of 300 saves an enormous amount of the 2 GB you have.

For packaging itself, the only dependencies worth having are Pillow for covers and reportlab for PDFs. Everything else is standard library. Every dependency you add to a 2 GB box is a future 3 a.m. debugging session.

Packaging is half the sale

A zip with a real 1280x720 cover and a 600x600 thumbnail sells. A bare file does not, and I have the sales numbers to prove it on my own catalogue. pack_product.py bundles the files and renders both images in one command:

python pack_product.py my-product "My Product" "A short subtitle" 9

It writes the zip, cover, and thumbnail into a _system folder, and you can redirect it with --dir or a PACK_ROOT environment variable. No editing the script, no per-product config.

Where this all came from

None of this is theory. These are the exact scripts that packaged 39 finished products, 856 MB of output, out of a parent pipeline of roughly 19,000 lines, backed by 300+ pages of research into the platform rules the scripts enforce, all validated on that same 1 vCPU / 2 GB RAM box. I documented the whole method, including the prompt engine side and the sticker niche specifics, in the ai sticker factory playbook. If you want the scripts and the process behind them, that is the tool built from this work.

Get ai sticker factory playbook


Building digital products? Free guides & kits for digital product sellers.

來源:DEV Community · dev.to