Lưu tệp hình ảnh AI từ API: đặt tên, nén webp nhiều cỡ và viết thẻ alt
Sau khi API trả hình ảnh về: chọn png hay webp, đặt tên tệp không dấu dễ tìm, xuất ba cỡ cho web bằng Pillow, lưu kèm câu lệnh vẽ và viết thẻ alt tiếng Việt cho đúng.

Gọi API thành công mới là nửa việc. Nửa còn lại quyết định trang của bạn nhanh hay chậm, sáu tháng sau có tìm lại được hình ảnh không, và người dùng trình đọc màn hình có hiểu hình ảnh nói gì không. Bài này đi qua những việc sau khi chuỗi b64_json về tới máy: chọn định dạng, đặt tên, đổi cỡ và nén, lưu kèm thông tin để vẽ lại được, và viết thẻ alt cho tử tế. Mã mẫu bằng Python, có đoạn tương đương cho PHP.
Chọn định dạng ngay từ lúc gọi
API nhận output_format là png (mặc định), jpeg hoặc webp. Chọn đúng từ đầu tiết kiệm một bước chuyển đổi.
| Định dạng | Khi nào dùng | Ghi chú |
|---|---|---|
webp | Hình ảnh cho web, mạng xã hội, sàn thương mại | Nhẹ nhất ở cùng chất lượng nhìn thấy; hình ảnh khổ 1536×1024 thường chỉ vài trăm KB |
png | Cần giữ nguyên chất lượng để còn chỉnh sửa nhiều lần trong Photoshop | Nặng gấp nhiều lần webp; đừng đưa thẳng lên web |
jpeg | Hệ thống cũ không đọc được webp (một số plugin, phần mềm in ấn) | Không có nền trong suốt, nhưng hình ảnh từ API vốn không có nền trong suốt |
Quy tắc thực tế: gọi webp cho mọi thứ đăng lên mạng, chỉ gọi png cho hình ảnh sẽ qua tay người thiết kế. Hình ảnh tải từ trang web của AI Hình Ảnh cũng là webp.
Đặt tên tệp: không dấu, có nghĩa, có ngày
Tên kiểu a8f3c1.webp hay image (17).webp là món nợ để lại cho chính bạn sáu tháng sau. Một khuôn tên dễ dùng:
```
<chủ đề không dấu>-<mã hoặc số thứ tự>-<yymmdd>.webp
bun-cha-ha-noi-01-261016.webp
bt-chen-05-2-261016.webp
```
- Không dấu, chữ thường, gạch ngang: chạy được trên mọi máy chủ, mọi hệ điều hành, đường dẫn không bị mã hoá thành
%C3%A1…. - Có chủ đề: tìm bằng tên tệp được, và công cụ tìm kiếm cũng đọc tên tệp như một gợi ý về nội dung.
- Có ngày: vẽ lại cùng chủ đề không đè tệp cũ; trình duyệt và Cloudflare không giữ bản cũ trong bộ nhớ đệm khi bạn thay hình ảnh.
Hàm bỏ dấu tiếng Việt cho tên tệp (chú ý chữ "đ" không tách được bằng Unicode, phải đổi tay):
```python
import re
import unicodedata
def khong_dau(s: str) -> str:
s = s.replace("đ", "d").replace("Đ", "D")
s = unicodedata.normalize("NFD", s)
s = "".join(c for c in s if unicodedata.category(c) != "Mn")
s = re.sub(r"[^a-zA-Z0-9]+", "-", s).strip("-").lower()
return s[:60] or "hinh-anh"
# khong_dau("Bún chả Hà Nội — quán đầu ngõ") -> "bun-cha-ha-noi-quan-dau-ngo"
```
Xuất nhiều cỡ cho web
Hình ảnh khổ 3:2 từ API rộng 1536 px. Trên điện thoại, hình đầu bài hiển thị chỉ rộng khoảng 400 px; gửi nguyên 1536 px là bắt người xem tải gấp nhiều lần cần thiết. Cách làm chuẩn là xuất vài cỡ và để trình duyệt chọn.
```python
import base64
import json
import time
from pathlib import Path
from PIL import Image # pip install pillow
CO = (1200, 768, 480) # độ rộng các bản xuất
def luu(kq: dict, chu_de: str, cau_lenh: str, thu_muc="kho") -> list:
"""kq: JSON trả về từ /v1/images/generations (response_format mặc định b64_json)."""
ngay = time.strftime("%y%m%d")
goc = Path(thu_muc) / "goc" / time.strftime("%Y-%m")
web = Path(thu_muc) / "web" / time.strftime("%Y-%m")
goc.mkdir(parents=True, exist_ok=True)
web.mkdir(parents=True, exist_ok=True)
ten_goc = khong_dau(chu_de)
ra = []
for i, d in enumerate(kq["data"], 1):
ten = f"{ten_goc}-{i:02d}-{ngay}"
tep_goc = goc / f"{ten}.webp"
tep_goc.write_bytes(base64.b64decode(d["b64_json"]))
im = Image.open(tep_goc).convert("RGB")
for w in CO:
if w >= im.width:
continue
h = round(im.height * w / im.width)
im.resize((w, h), Image.LANCZOS).save(
web / f"{ten}-{w}.webp", "WEBP", quality=78, method=6)
(goc / f"{ten}.json").write_text(json.dumps({
"cau_lenh": cau_lenh, "model": kq.get("model"),
"kich_thuoc": [im.width, im.height], "ngay": ngay,
"diem": kq.get("usage", {}).get("credits"),
}, ensure_ascii=False, indent=1), encoding="utf-8")
ra.append(ten)
return ra
```
Những lựa chọn trong đoạn mã:
- Giữ bản gốc riêng trong
goc/, không bao giờ ghi đè. Bản web có thể xuất lại bất cứ lúc nào từ bản gốc, bản gốc mất là phải vẽ lại. - Thư mục theo tháng: một thư mục vài nghìn tệp vẫn chạy, nhưng mở bằng trình quản lý tệp hay đồng bộ lên kho lưu đám mây sẽ chậm.
quality=78,method=6: chất lượng 75–82 là vùng mắt thường khó phân biệt với bản gốc trên màn hình;method=6nén chậm hơn nhưng tệp nhỏ hơn, đáng giá khi chạy một lần.- Bỏ qua cỡ lớn hơn bản gốc: đừng phóng to hình ảnh, chỉ thêm dung lượng mà không thêm chi tiết.
Đoạn tương đương bằng PHP GD
```php
<?php
function xuat_webp(string $tepGoc, string $thuMuc, string $ten, array $co = [1200, 768, 480]): void {
$im = imagecreatefromstring(file_get_contents($tepGoc));
$w0 = imagesx($im); $h0 = imagesy($im);
foreach ($co as $w) {
if ($w >= $w0) continue;
$h = (int) round($h0 * $w / $w0);
$nho = imagecreatetruecolor($w, $h);
imagecopyresampled($nho, $im, 0, 0, 0, 0, $w, $h, $w0, $h0);
imagewebp($nho, "$thuMuc/$ten-$w.webp", 78);
imagedestroy($nho);
}
imagedestroy($im);
}
```
Kiểm tra máy chủ có hỗ trợ webp không bằng php -r 'var_dump(function_exists("imagewebp"));'.
Dùng nhiều cỡ trong HTML
```html
<img src="/kho/web/2026-10/bun-cha-ha-noi-01-261016-768.webp"
srcset="/kho/web/2026-10/bun-cha-ha-noi-01-261016-480.webp 480w,
/kho/web/2026-10/bun-cha-ha-noi-01-261016-768.webp 768w,
/kho/web/2026-10/bun-cha-ha-noi-01-261016-1200.webp 1200w"
sizes="(max-width: 700px) 100vw, 700px"
width="1200" height="800" loading="lazy"
alt="Suất bún chả với chả nướng than hoa, rổ rau sống và bát nước chấm đu đủ xanh trên bàn gỗ quán vỉa hè">
```
Hai chi tiết hay quên: width và height (tỉ lệ thật của hình ảnh) giúp trang không giật khi hình ảnh tải xong; loading="lazy" cho mọi hình ảnh trừ hình đầu bài nằm ngay màn hình đầu tiên.
Viết thẻ alt cho đúng
Thẻ alt là chữ mà trình đọc màn hình đọc cho người khiếm thị, và là thứ công cụ tìm kiếm dùng để hiểu hình ảnh. Nó không phải chỗ nhồi từ khoá.
| Kiểu alt | Ví dụ | Đánh giá |
|---|---|---|
| Bỏ trống | alt="" | Chỉ đúng cho hình ảnh thuần trang trí |
| Tên tệp | bun-cha-01 | Vô dụng với người đọc |
| Nhồi từ khoá | "bún chả, bún chả Hà Nội, bún chả ngon, quán bún chả" | Gây khó chịu, không giúp gì |
| Tả đúng nội dung | "Suất bún chả với chả nướng than hoa, rổ rau sống và bát nước chấm trên bàn gỗ" | Tốt |
| Tả đúng và nói rõ là minh hoạ khi cần | "Minh hoạ: góc bếp gia đình với nồi kho tộ trên bếp than" | Tốt cho bài cần minh bạch |
Một mẹo cho người làm hàng loạt: viết alt từ ý của câu lệnh vẽ, không dịch máy móc. Câu lệnh tiếng Anh tả cảnh cho máy vẽ; alt tả cảnh cho người đọc tiếng Việt. Cùng nội dung, khác người nhận. Giữ alt dưới khoảng 125 ký tự, bỏ những từ kỹ thuật như "realistic photo", "shallow depth of field" vốn chỉ có nghĩa với máy vẽ.
Nếu bài viết có quy định gắn nhãn nội dung AI, alt là một chỗ hợp lý để thêm chữ "Minh hoạ". Xem thêm bài gắn nhãn hình ảnh AI trên các nền tảng.
Lưu kèm câu lệnh vẽ: tệp JSON bên cạnh
Tệp .json cùng tên với bản gốc ghi câu lệnh, hạng, kích thước, ngày và số điểm. Vì sao đáng làm:
- Vẽ lại được khi cần cỡ khác hay muốn biến thể, chỉ cần đọc lại câu lệnh.
- Trả lời được khi khách hàng, đối tác hỏi "hình này từ đâu ra".
- Tính được chi phí của từng dự án bằng cách cộng trường
diem.
Không thể vẽ lại y hệt một hình ảnh: mỗi lượt vẽ dùng hạt giống ngẫu nhiên và không chọn được hạt giống. Câu lệnh lưu lại giúp vẽ được hình ảnh cùng tinh thần, không phải bản sao. Vì thế bản gốc luôn quý hơn câu lệnh.
Khi dùng response_format: "url"
Nếu gọi API với response_format là url, kết quả trả về đường dẫn tới tệp trên aihinhanh.com thay vì chuỗi base64. Tiện cho thử nghiệm, nhưng đừng nhúng thẳng đường dẫn đó vào trang của bạn: hãy tải tệp về kho của mình ngay khi nhận, rồi đi tiếp quy trình đặt tên, đổi cỡ như trên. Kho của bạn là nơi lưu lâu dài, đường dẫn trả về chỉ là chỗ nhận hàng.
Lỗi hay gặp
| Triệu chứng | Nguyên nhân | Sửa |
|---|---|---|
| Trang tải chậm dù đã dùng webp | Đưa bản 1536 px cho mọi màn hình | Xuất nhiều cỡ, dùng srcset |
| Thay hình ảnh mà người xem vẫn thấy hình cũ | Cùng tên tệp, bộ nhớ đệm giữ bản cũ | Tên tệp có ngày; hoặc xoá bộ nhớ đệm Cloudflare |
Tên tệp hiện %C3%A1 trên thanh địa chỉ | Tên tệp có dấu tiếng Việt | Dùng hàm bỏ dấu |
| Bản web mờ, có vệt khối | quality quá thấp (dưới 60) | Đặt 75–82 |
| Mất bản gốc sau khi chỉnh | Ghi đè lên tệp tải về | Tách thư mục goc/ và web/ |
Cả quy trình này cắm thẳng vào đoạn mã ở bài tạo hàng loạt hình ảnh từ CSV hoặc plugin ở bài hình ảnh đầu bài WordPress.



