feat(posts): adopt consultant rulings on decoupled slug, decoding contracts, and pillow laplacian filter
This commit is contained in:
1 parent
0e31199510
commit
c49c4ff725
8 files changed
+249
-94
No files matched your search
File renamed without changes.
@@ -159,8 +159,50 @@ def generate_cover(slug, topic_metaphor):
|
||||
A batch script that blindly accepts images will inevitably check in broken assets. I introduced
|
||||
an automated **visual clearance audit** using Python Pillow with an explicit tolerance buffer:
|
||||
|
||||
1. **The 45% Target / 35% Audit Buffer**: While the diffusion prompt instructs the model to preserve the upper 45% as negative space, diffusion gradients naturally bleed across compositional boundaries. The automated audit enforces a strict red-line on the core **upper 35%** headline bounding box, giving the model a 10% transition buffer. The script measures pixel luminance and edge variance in that 35% zone; if high-frequency noise or bright elements bleed into it, the image fails clearance and is regenerated with an alternate seed.
|
||||
2. **Dimension & Format Compression**: Output images are automatically resized to canonical Open Graph dimensions (`1200×630`), converted to 85%-quality WebP, and verified for sub-100KB file sizes.
|
||||
1. **The 45% Target / 35% Audit Buffer**: While the diffusion prompt instructs the model to preserve the upper 45% as negative space, diffusion gradients naturally bleed across compositional boundaries. The automated audit enforces a strict red-line on the core **upper 35%** headline bounding box, giving the model a 10% transition buffer.
|
||||
2. **Mean Luminance vs. Laplacian Edge Variance**: Checking only average brightness creates a dangerous blind spot: high-contrast dark wireframes or glyph hallucinations still have low mean luminance, but utterly destroy title readability. To solve this without adding heavy OpenCV dependencies, the script convolves a 3×3 Laplacian high-pass kernel directly via pure Pillow (`ImageFilter.Kernel`) and measures standard deviation across the edge map.
|
||||
3. **Dimension & Format Compression**: Output images are automatically resized to canonical Open Graph dimensions (`1200×630`), converted to 85%-quality WebP, and verified for sub-100KB file sizes.
|
||||
|
||||
<details>
|
||||
<summary>View pure Pillow negative-space audit implementation (Python excerpt)</summary>
|
||||
|
||||
```python
|
||||
from PIL import Image, ImageFilter, ImageStat
|
||||
|
||||
# 45% negative-space prompt target -> 35% strict audit zone (10% diffusion transition buffer)
|
||||
SAFE_ZONE_RATIO = 0.35
|
||||
MAX_MEAN_LUMINANCE = 28.0 # Enforce zinc-950 (#09090b) dark base
|
||||
MAX_LAPLACIAN_STDDEV = 12.0 # Block high-frequency wireframe/geometry bleed into title zone
|
||||
|
||||
# 3x3 Laplacian high-pass kernel to isolate sharp edges and stray glyph hallucinations
|
||||
LAPLACIAN_KERNEL = ImageFilter.Kernel(
|
||||
size=(3, 3),
|
||||
kernel=[-1, -1, -1, -1, 8, -1, -1, -1, -1],
|
||||
scale=1,
|
||||
offset=0,
|
||||
)
|
||||
|
||||
def audit_top_negative_space(img_path: str) -> tuple[bool, str]:
|
||||
with Image.open(img_path) as img:
|
||||
w, h = img.size
|
||||
# Crop top 35% title safe zone and convert to grayscale (L)
|
||||
top_zone = img.crop((0, 0, w, int(h * SAFE_ZONE_RATIO))).convert("L")
|
||||
|
||||
# Gate 1: Mean luminance check (catches bright glow or color washes)
|
||||
mean_lum = ImageStat.Stat(top_zone).mean[0]
|
||||
if mean_lum > MAX_MEAN_LUMINANCE:
|
||||
return False, f"REJECT_LUMINANCE: {mean_lum:.1f} > {MAX_MEAN_LUMINANCE}"
|
||||
|
||||
# Gate 2: Laplacian edge variance check (catches dark-but-busy wireframes/text artifacts)
|
||||
edge_map = top_zone.filter(LAPLACIAN_KERNEL)
|
||||
edge_std = ImageStat.Stat(edge_map).stddev[0]
|
||||
if edge_std > MAX_LAPLACIAN_STDDEV:
|
||||
return False, f"REJECT_HIGH_FREQ_CLUTTER: edge_std {edge_std:.1f} > {MAX_LAPLACIAN_STDDEV}"
|
||||
|
||||
return True, f"PASS (lum={mean_lum:.1f}, edge_std={edge_std:.1f})"
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -71,6 +71,8 @@ Notice the asymmetry: **MP4 is an end-user distribution container with strict pa
|
||||
while Matroska is a high-fidelity archival container.** Treating them identically with `-map 0`
|
||||
guarantees pipeline crashes.
|
||||
|
||||
**Why not standardize exclusively on MKV?** Because container selection is dictated by downstream client decoding contracts. Native Apple playback engines (`AVPlayer` on iOS/macOS and WebKit `<video>`) strictly require ISOBMFF/MP4 containers, hardware-decode only `tx3g` (`mov_text`) closed-caption tracks, and read track labels exclusively from the `udta/name` atom. Conversely, dedicated desktop and custom media clients (`mpv`, `VLC`, or `libass`-backed players) natively parse Matroska attachments, rendering vector ASS subtitles with embedded TTF/OTF fonts bit-for-bit. A production remuxing pipeline cannot force users to change players; it must deterministically adapt container internals to the target runtime.
|
||||
|
||||
---
|
||||
|
||||
## Architecting a deterministic tracks planner
|
||||
|
||||
File renamed without changes.
@@ -149,8 +149,50 @@ def generate_cover(slug, topic_metaphor):
|
||||
|
||||
如果批处理流水线对生成结果不做验收,依然会有缺陷图片漏网。我在入库阶段加入了基于 Python Pillow 的**顶部留白区域净度审计**,并引入了 10% 的工程容差缓冲带:
|
||||
|
||||
1. **45% 留白目标与 35% 审计红线的容差缓冲**:虽然 Prompt 明确要求模型在顶部预留 45% 的负空间,但扩散模型在构图交界处往往存在渐变溢出。因此,自动化审计将核心红线设定在**顶部 35%** 的绝对标题选区内,给予模型 10% 的过渡缓冲带。脚本扫描该选区内的平均亮度和边缘方差,若检测到密集高频杂纹或亮度超标,立即判定“构图过满”,自动废弃并换用新随机种子重新生成。
|
||||
2. **规范化转码**:统一缩放至 Open Graph 标准的 `1200×630` 规格,输出为 85% 质量等级的现代 WebP 格式,严格确保单张体积控制在 100KB 以内。
|
||||
1. **45% 留白目标与 35% 审计红线的容差缓冲**:虽然 Prompt 明确要求模型在顶部预留 45% 的负空间,但扩散模型在构图交界处往往存在渐变溢出。因此,自动化审计将核心红线设定在**顶部 35%** 的绝对标题选区内,给予模型 10% 的过渡缓冲带。
|
||||
2. **平均亮度与拉普拉斯边缘方差双重门禁**:单纯检查平均亮度存在严重盲区——暗色背景上的高对比度青色线框或乱码文字同样具备极低的平均亮度,却会彻底摧毁大标题的可读性。为了避免引入 OpenCV 等重型依赖,审计脚本直接利用纯 Pillow 内置的 3×3 拉普拉斯卷积核(`ImageFilter.Kernel`)提取高频边缘图,并计算标准差(`stddev`)进行拦截。
|
||||
3. **规范化转码**:统一缩放至 Open Graph 标准的 `1200×630` 规格,输出为 85% 质量等级的现代 WebP 格式,严格确保单张体积控制在 100KB 以内。
|
||||
|
||||
<details>
|
||||
<summary>点击查看纯 Pillow 留白净度审计算法实现(Python 关键片段)</summary>
|
||||
|
||||
```python
|
||||
from PIL import Image, ImageFilter, ImageStat
|
||||
|
||||
# 提示词要求 45% 留白 -> 核心 35% 严格标题选区(预留 10% 扩散过渡缓冲)
|
||||
SAFE_ZONE_RATIO = 0.35
|
||||
MAX_MEAN_LUMINANCE = 28.0 # 强制收敛至 zinc-950 (#09090b) 暗色基底
|
||||
MAX_LAPLACIAN_STDDEV = 12.0 # 阻断高频线框与伪文字幻觉侵入标题区
|
||||
|
||||
# 3x3 拉普拉斯高通卷积核,用于隔离尖锐边缘与孤立噪点
|
||||
LAPLACIAN_KERNEL = ImageFilter.Kernel(
|
||||
size=(3, 3),
|
||||
kernel=[-1, -1, -1, -1, 8, -1, -1, -1, -1],
|
||||
scale=1,
|
||||
offset=0,
|
||||
)
|
||||
|
||||
def audit_top_negative_space(img_path: str) -> tuple[bool, str]:
|
||||
with Image.open(img_path) as img:
|
||||
w, h = img.size
|
||||
# 裁剪顶部 35% 标题安全区并转为灰度图 (L)
|
||||
top_zone = img.crop((0, 0, w, int(h * SAFE_ZONE_RATIO))).convert("L")
|
||||
|
||||
# 闸门 1: 平均亮度检测(拦截大面积泛光与色块侵蚀)
|
||||
mean_lum = ImageStat.Stat(top_zone).mean[0]
|
||||
if mean_lum > MAX_MEAN_LUMINANCE:
|
||||
return False, f"REJECT_LUMINANCE: 亮度超标 {mean_lum:.1f} > {MAX_MEAN_LUMINANCE}"
|
||||
|
||||
# 闸门 2: 拉普拉斯高频边缘方差检测(拦截暗色背景下的线框与文字幻觉)
|
||||
edge_map = top_zone.filter(LAPLACIAN_KERNEL)
|
||||
edge_std = ImageStat.Stat(edge_map).stddev[0]
|
||||
if edge_std > MAX_LAPLACIAN_STDDEV:
|
||||
return False, f"REJECT_HIGH_FREQ_CLUTTER: 边缘噪点超标 edge_std {edge_std:.1f} > {MAX_LAPLACIAN_STDDEV}"
|
||||
|
||||
return True, f"PASS (lum={mean_lum:.1f}, edge_std={edge_std:.1f})"
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -64,6 +64,8 @@ ffmpeg -i source.mkv -map 0 -c:v libx265 -c:a copy output.mp4
|
||||
|
||||
这个对比揭示了一个核心本质:**MP4 是面向最终用户的轻量级分发容器,拥有严格的解析器防线;而 Matroska 是面向母带保真归档的工业级容器。** 使用泛化的 `-map 0` 去混流两者,注定遭遇生产崩溃。
|
||||
|
||||
**为什么不干脆全量统一为 MKV 容器?** 因为容器封装格式是由下游终端的解码契约决定的。Apple 原生播放引擎(iOS/macOS 上的 `AVPlayer` 及 WebKit 内核)强制要求 ISOBMFF/MP4 容器,在字幕层仅原生解析 `tx3g`(`mov_text`)格式,且仅从 `udta/name` 原子节点读取音轨名称;而桌面端或内嵌 `libass` 渲染引擎的专用客户端(如 `mpv`、`VLC`)则能原生解析 Matroska 容器中的矢量 ASS 字幕与内嵌 TTF/OTF 字体流。生产级混流管线不能要求终端用户更换播放器,而必须在入库期根据目标运行时确定性地适配容器内部结构。
|
||||
|
||||
---
|
||||
|
||||
## 确定性轨道规划器架构
|
||||
|
||||
Reference in new issue
Block a user