Skip to content

Commit 82275ce

Browse files
committed
chore: sync all 86 ES audio entries into blogData
1 parent fccb8e0 commit 82275ce

6 files changed

Lines changed: 160 additions & 36 deletions

File tree

front/public/blog/audio-es/curiosities/network-science-communities-centrality.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,11 @@
33
"category": "curiosities",
44
"lang": "es",
55
"voice": "es-CO-GonzaloNeural",
6-
"hash": "7a3a49f386fc2ed7c5382a326269e08eaa738587a1d9b81fe523e6ddcb1f2a9b",
6+
"hash": "a8b4ae449043e0e7e7c7cb2315e48ed22d835b0a6520f6a999f1568ceac432e6",
77
"sourceHash": "634159cff0424782b9f2ae8348a693fcc16dc6263c96fa822e0f293e3d41a9ca",
8-
"durationSec": 1505.472,
9-
"byteSize": 9032832,
10-
"narrationWordCount": 4001,
8+
"durationSec": 1505.136,
9+
"byteSize": 9030816,
10+
"narrationWordCount": 3999,
1111
"audioUrl": "/blog/audio-es/curiosities/network-science-communities-centrality.mp3",
1212
"translationModel": "gemma4:latest"
1313
}
Binary file not shown.

front/public/blog/audio-es/curiosities/network-science-communities-centrality.narration.json

Lines changed: 2 additions & 2 deletions
Large diffs are not rendered by default.

front/public/blog/audio-es/manifest-es.json

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"lang": "es",
33
"voice": "es-CO-GonzaloNeural",
4-
"generatedAt": 1776030427,
4+
"generatedAt": 1776031248,
55
"posts": {
66
"curiosities/algebraic-number-theory-when-factorization-breaks": {
77
"slug": "algebraic-number-theory-when-factorization-breaks",
@@ -99,11 +99,11 @@
9999
"category": "curiosities",
100100
"lang": "es",
101101
"voice": "es-CO-GonzaloNeural",
102-
"hash": "7a3a49f386fc2ed7c5382a326269e08eaa738587a1d9b81fe523e6ddcb1f2a9b",
102+
"hash": "a8b4ae449043e0e7e7c7cb2315e48ed22d835b0a6520f6a999f1568ceac432e6",
103103
"sourceHash": "634159cff0424782b9f2ae8348a693fcc16dc6263c96fa822e0f293e3d41a9ca",
104-
"durationSec": 1505.472,
105-
"byteSize": 9032832,
106-
"narrationWordCount": 4001,
104+
"durationSec": 1505.136,
105+
"byteSize": 9030816,
106+
"narrationWordCount": 3999,
107107
"audioUrl": "/blog/audio-es/curiosities/network-science-communities-centrality.mp3",
108108
"translationModel": "gemma4:latest"
109109
},
@@ -1048,11 +1048,11 @@
10481048
"category": "research",
10491049
"lang": "es",
10501050
"voice": "es-CO-GonzaloNeural",
1051-
"hash": "50b2d68600601ec54e1865e096f0b973e69b41c25cbc90afeef58a3a81f1ebfe",
1051+
"hash": "a93909f3c8565c0630a8e799cffe86d39b297e128c668567a8b871b81dfe3522",
10521052
"sourceHash": "38a5c83a9baa16c2973452954afb5e3addbdcbedad9d713c088d9c8002fa4e4a",
1053-
"durationSec": 1783.968,
1054-
"byteSize": 10703808,
1055-
"narrationWordCount": 4837,
1053+
"durationSec": 1787.136,
1054+
"byteSize": 10722816,
1055+
"narrationWordCount": 4859,
10561056
"audioUrl": "/blog/audio-es/research/mamba-selective-state-spaces.mp3",
10571057
"translationModel": "gemma4:latest"
10581058
},

front/scripts/generate-blog-pdf.js

Lines changed: 24 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -317,6 +317,7 @@ async function fetchMermaidPNG(code) {
317317
return fs.readFileSync(pngCachePath);
318318
}
319319

320+
// Try with htmlLabels:false (SVG text labels, needed for sharp/librsvg rasterization)
320321
const krokiSource = toKrokiMermaidSource(code);
321322
const body = Buffer.from(krokiSource, 'utf8');
322323
const { statusCode, body: resp } = await krokiPost('/mermaid/svg', body);
@@ -328,17 +329,25 @@ async function fetchMermaidPNG(code) {
328329
} catch (e) {
329330
console.warn(` ⚠ Mermaid SVG rasterize failed (${e.message}); falling back to Kroki PNG`);
330331
}
331-
} else if (statusCode !== 200) {
332-
console.warn(` ⚠ Kroki SVG ${statusCode}: ${resp.toString('utf8').slice(0, 120)}`);
333332
}
334333

335334
const pngFallback = await krokiPost('/mermaid/png', body);
336335
if (pngFallback.statusCode === 200 && pngFallback.body.length) {
337336
fs.writeFileSync(pngCachePath, pngFallback.body);
338337
return pngFallback.body;
339338
}
340-
if (pngFallback.statusCode !== 200) {
341-
console.warn(` ⚠ Kroki PNG ${pngFallback.statusCode}: ${pngFallback.body.toString('utf8').slice(0, 120)}`);
339+
340+
// htmlLabels:false can break diagrams with \n in labels on some Kroki versions.
341+
// Fallback: request PNG with the original code (Kroki's PNG uses a headless browser
342+
// that renders foreignObject / HTML labels correctly).
343+
const originalBody = Buffer.from(code, 'utf8');
344+
const originalPng = await krokiPost('/mermaid/png', originalBody);
345+
if (originalPng.statusCode === 200 && originalPng.body.length) {
346+
fs.writeFileSync(pngCachePath, originalPng.body);
347+
return originalPng.body;
348+
}
349+
if (originalPng.statusCode !== 200) {
350+
console.warn(` ⚠ Kroki PNG (all attempts) ${originalPng.statusCode}: ${originalPng.body.toString('utf8').slice(0, 120)}`);
342351
}
343352
return null;
344353
}
@@ -1466,24 +1475,19 @@ function drawCoverCollage(doc, pw, ph, imgPaths) {
14661475
return;
14671476
}
14681477

1469-
// n >= 4 — full-width hero + lower mosaic (cycles through remaining headers)
1470-
const heroH = Math.round(ph * 0.44);
1471-
drawCoverImageCell(doc, imgPaths[0], 0, 0, pw, heroH);
1472-
1473-
const galleryTop = heroH + g;
1474-
const galleryH = ph - galleryTop;
1475-
const rest = n - 1;
1476-
const cols = Math.min(7, Math.max(3, Math.ceil(Math.sqrt(rest * (pw / Math.max(galleryH, 1)) * 1.15))));
1477-
const rows = Math.ceil(rest / cols);
1478+
// n >= 4 — uniform grid, all cells roughly the same size
1479+
const aspect = pw / ph;
1480+
const cols = Math.min(8, Math.max(3, Math.round(Math.sqrt(n * aspect))));
1481+
const rows = Math.ceil(n / cols);
14781482
const cellW = (pw - g * (cols - 1)) / cols;
1479-
const cellH = (galleryH - g * (rows - 1)) / rows;
1483+
const cellH = (ph - g * (rows - 1)) / rows;
14801484

14811485
let cell = 0;
14821486
for (let row = 0; row < rows; row++) {
14831487
for (let col = 0; col < cols; col++) {
1484-
const imgIdx = 1 + (cell % rest);
1488+
const imgIdx = cell % n;
14851489
const x = col * (cellW + g);
1486-
const y = galleryTop + row * (cellH + g);
1490+
const y = row * (cellH + g);
14871491
drawCoverImageCell(doc, imgPaths[imgIdx], x, y, cellW, cellH);
14881492
cell += 1;
14891493
}
@@ -1496,15 +1500,15 @@ function drawCoverCollage(doc, pw, ph, imgPaths) {
14961500
* without the directional-light noise of the old 3-gradient version.
14971501
*/
14981502
function drawCoverAtmosphericOverlay(doc, pw, ph) {
1499-
// Main tonal wash — top slightly lighter than bottom for depth.
1503+
// Main tonal wash — lighter so the collage shows through as visible texture.
15001504
const wash = doc.linearGradient(0, 0, 0, ph)
1501-
.stop(0, '#0b1220', 0.86)
1502-
.stop(1, '#020617', 0.94);
1505+
.stop(0, '#0b1220', 0.55)
1506+
.stop(1, '#020617', 0.72);
15031507
doc.rect(0, 0, pw, ph).fill(wash);
15041508

15051509
// Soft left-column shadow to seat the typography without forcing a hard edge.
15061510
const shadow = doc.linearGradient(0, 0, pw * 0.55, 0)
1507-
.stop(0, '#020617', 0.45)
1511+
.stop(0, '#020617', 0.40)
15081512
.stop(1, '#020617', 0);
15091513
doc.rect(0, 0, pw * 0.55, ph).fill(shadow);
15101514
}

0 commit comments

Comments
 (0)