luckiest-co 1.0.32 → 1.0.34
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/commands/plan.md +1 -0
- package/package.json +1 -1
- package/skills/luckiest-plan/SKILL.md +1 -0
- package/skills/luckiest-research/CHANGELOG.md +5 -0
- package/skills/luckiest-research/SKILL.md +8 -4
- package/skills/luckiest-video-studio/ATTRIBUTION.md +11 -0
- package/skills/luckiest-video-studio/CHANGELOG.md +56 -0
- package/skills/luckiest-video-studio/SKILL.md +35 -7
- package/skills/luckiest-video-studio/references/audio.md +61 -10
- package/skills/luckiest-video-studio/references/lessons.md +44 -0
- package/skills/luckiest-video-studio/references/step-2-plan.md +32 -1
- package/skills/luckiest-video-studio/references/step-3-compose.md +28 -0
- package/skills/luckiest-video-studio/references/step-4-deliver.md +24 -1
- package/skills/luckiest-video-studio/references/storyboard.md +24 -3
- package/skills/luckiest-video-studio/scripts/qa.mjs +167 -5
- package/skills/luckiest-video-studio/scripts/qa.test.mjs +99 -1
- package/skills/luckiest-video-studio/scripts/render-scenes.mjs +196 -71
- package/skills/luckiest-video-studio/scripts/render-scenes.test.mjs +109 -0
- package/skills/luckiest-video-studio/scripts/sfx-cues.mjs +116 -0
- package/skills/luckiest-video-studio/scripts/sfx-cues.test.mjs +76 -0
- package/skills/luckiest-video-studio/scripts/stamp-format.mjs +26 -0
- package/skills/luckiest-video-studio/scripts/storyboard.schema.json +23 -0
- package/skills/luckiest-video-studio/templates/logo-line-draw.html +12 -5
- package/skills/luckiest-video-studio-art-director/ATTRIBUTION.md +1 -0
- package/skills/luckiest-video-studio-art-director/CHANGELOG.md +8 -0
- package/skills/luckiest-video-studio-art-director/SKILL.md +18 -5
- package/skills/luckiest-video-studio-cards/CHANGELOG.md +18 -0
- package/skills/luckiest-video-studio-cards/SKILL.md +22 -7
- package/skills/luckiest-video-studio-cards/packs/01-paper-collage/cards/tier1/t1-overview-agenda.html +17 -6
- package/skills/luckiest-video-studio-cards/packs/01-paper-collage/cards/tier1/t1-overview-bigtype.html +15 -5
- package/skills/luckiest-video-studio-cards/packs/01-paper-collage/cards/tier1/t1-overview-board.html +20 -6
- package/skills/luckiest-video-studio-cards/packs/01-paper-collage/cards/tier1/t1-overview-checklist.html +27 -6
- package/skills/luckiest-video-studio-cards/packs/01-paper-collage/cards/tier1/t1-overview-compare.html +40 -9
- package/skills/luckiest-video-studio-cards/packs/01-paper-collage/cards/tier1/t1-overview-deck.html +26 -6
- package/skills/luckiest-video-studio-cards/packs/01-paper-collage/cards/tier1/t1-overview-dossier.html +28 -9
- package/skills/luckiest-video-studio-cards/packs/01-paper-collage/cards/tier1/t1-overview-filmstrip.html +36 -5
- package/skills/luckiest-video-studio-cards/packs/01-paper-collage/cards/tier1/t1-overview-grid6.html +24 -6
- package/skills/luckiest-video-studio-cards/packs/01-paper-collage/cards/tier1/t1-overview-indexset.html +34 -6
- package/skills/luckiest-video-studio-cards/packs/01-paper-collage/cards/tier1/t1-overview-maplegend.html +39 -8
- package/skills/luckiest-video-studio-cards/packs/01-paper-collage/cards/tier1/t1-overview-matrix.html +35 -7
- package/skills/luckiest-video-studio-cards/packs/01-paper-collage/cards/tier1/t1-overview-numlist.html +26 -7
- package/skills/luckiest-video-studio-cards/packs/01-paper-collage/cards/tier1/t1-overview-outline.html +26 -6
- package/skills/luckiest-video-studio-cards/packs/01-paper-collage/cards/tier1/t1-overview-phases.html +34 -7
- package/skills/luckiest-video-studio-cards/packs/01-paper-collage/cards/tier1/t1-overview-quad.html +41 -10
- package/skills/luckiest-video-studio-cards/packs/01-paper-collage/cards/tier1/t1-overview-roadmap.html +66 -17
- package/skills/luckiest-video-studio-cards/packs/01-paper-collage/cards/tier1/t1-overview-stepper.html +42 -7
- package/skills/luckiest-video-studio-cards/packs/01-paper-collage/cards/tier1/t1-overview-toc.html +26 -8
- package/skills/luckiest-video-studio-cards/packs/01-paper-collage/cards/tier1/t1-overview-vtimeline.html +35 -9
- package/skills/luckiest-video-studio-cards/packs/01-paper-collage/cards/tier1/t1-section-bracket.html +16 -4
- package/skills/luckiest-video-studio-cards/packs/01-paper-collage/cards/tier1/t1-section-circle.html +21 -5
- package/skills/luckiest-video-studio-cards/packs/01-paper-collage/cards/tier1/t1-section-classified.html +25 -7
- package/skills/luckiest-video-studio-cards/packs/01-paper-collage/cards/tier1/t1-section-collage.html +27 -9
- package/skills/luckiest-video-studio-cards/packs/01-paper-collage/cards/tier1/t1-section-correction.html +19 -7
- package/skills/luckiest-video-studio-cards/packs/01-paper-collage/cards/tier1/t1-section-crt.html +15 -4
- package/skills/luckiest-video-studio-cards/packs/01-paper-collage/cards/tier1/t1-section-cutout.html +18 -8
- package/skills/luckiest-video-studio-cards/packs/01-paper-collage/cards/tier1/t1-section-fullbleed.html +18 -5
- package/skills/luckiest-video-studio-cards/packs/01-paper-collage/cards/tier1/t1-section-highlight.html +15 -5
- package/skills/luckiest-video-studio-cards/packs/01-paper-collage/cards/tier1/t1-section-indexcard.html +18 -5
- package/skills/luckiest-video-studio-cards/packs/01-paper-collage/cards/tier1/t1-section-map.html +20 -8
- package/skills/luckiest-video-studio-cards/packs/01-paper-collage/cards/tier1/t1-section-markerbox.html +12 -5
- package/skills/luckiest-video-studio-cards/packs/01-paper-collage/cards/tier1/t1-section-numeral.html +21 -7
- package/skills/luckiest-video-studio-cards/packs/01-paper-collage/cards/tier1/t1-section-split.html +25 -9
- package/skills/luckiest-video-studio-cards/packs/01-paper-collage/cards/tier1/t1-section-stacked.html +26 -10
- package/skills/luckiest-video-studio-cards/packs/01-paper-collage/cards/tier1/t1-section-stamp.html +14 -5
- package/skills/luckiest-video-studio-cards/packs/01-paper-collage/cards/tier1/t1-section-ticker.html +26 -9
- package/skills/luckiest-video-studio-cards/packs/01-paper-collage/cards/tier1/t1-section-tornstrip.html +13 -4
- package/skills/luckiest-video-studio-cards/packs/01-paper-collage/cards/tier1/t1-stat-annotated.html +29 -9
- package/skills/luckiest-video-studio-cards/packs/01-paper-collage/cards/tier1/t1-stat-arc.html +25 -7
- package/skills/luckiest-video-studio-cards/packs/01-paper-collage/cards/tier1/t1-stat-axis.html +34 -14
- package/skills/luckiest-video-studio-cards/packs/01-paper-collage/cards/tier1/t1-stat-bar.html +17 -8
- package/skills/luckiest-video-studio-cards/packs/01-paper-collage/cards/tier1/t1-stat-bracket.html +24 -8
- package/skills/luckiest-video-studio-cards/packs/01-paper-collage/cards/tier1/t1-stat-calendar.html +24 -9
- package/skills/luckiest-video-studio-cards/packs/01-paper-collage/cards/tier1/t1-stat-callout.html +24 -5
- package/skills/luckiest-video-studio-cards/packs/01-paper-collage/cards/tier1/t1-stat-columns.html +27 -9
- package/skills/luckiest-video-studio-cards/packs/01-paper-collage/cards/tier1/t1-stat-corner.html +22 -9
- package/skills/luckiest-video-studio-cards/packs/01-paper-collage/cards/tier1/t1-stat-dots.html +27 -8
- package/skills/luckiest-video-studio-cards/packs/01-paper-collage/cards/tier1/t1-stat-engraving.html +30 -8
- package/skills/luckiest-video-studio-cards/packs/01-paper-collage/cards/tier1/t1-stat-footnote.html +20 -8
- package/skills/luckiest-video-studio-cards/packs/01-paper-collage/cards/tier1/t1-stat-frac.html +24 -8
- package/skills/luckiest-video-studio-cards/packs/01-paper-collage/cards/tier1/t1-stat-heat.html +22 -8
- package/skills/luckiest-video-studio-cards/packs/01-paper-collage/cards/tier1/t1-stat-isotype.html +29 -8
- package/skills/luckiest-video-studio-cards/packs/01-paper-collage/cards/tier1/t1-stat-ledger.html +18 -6
- package/skills/luckiest-video-studio-cards/packs/01-paper-collage/cards/tier1/t1-stat-left.html +27 -10
- package/skills/luckiest-video-studio-cards/packs/01-paper-collage/cards/tier1/t1-stat-magnifier.html +21 -8
- package/skills/luckiest-video-studio-cards/packs/01-paper-collage/cards/tier1/t1-stat-map.html +21 -9
- package/skills/luckiest-video-studio-cards/packs/01-paper-collage/cards/tier1/t1-stat-meter.html +26 -9
- package/skills/luckiest-video-studio-cards/packs/01-paper-collage/cards/tier1/t1-stat-multiplier.html +27 -12
- package/skills/luckiest-video-studio-cards/packs/01-paper-collage/cards/tier1/t1-stat-odo.html +18 -5
- package/skills/luckiest-video-studio-cards/packs/01-paper-collage/cards/tier1/t1-stat-pack.html +41 -17
- package/skills/luckiest-video-studio-cards/packs/01-paper-collage/cards/tier1/t1-stat-photo.html +18 -7
- package/skills/luckiest-video-studio-cards/packs/01-paper-collage/cards/tier1/t1-stat-pie.html +25 -8
- package/skills/luckiest-video-studio-cards/packs/01-paper-collage/cards/tier1/t1-stat-postage.html +24 -8
- package/skills/luckiest-video-studio-cards/packs/01-paper-collage/cards/tier1/t1-stat-pricetag.html +25 -11
- package/skills/luckiest-video-studio-cards/packs/01-paper-collage/cards/tier1/t1-stat-quote.html +21 -8
- package/skills/luckiest-video-studio-cards/packs/01-paper-collage/cards/tier1/t1-stat-ranking.html +25 -10
- package/skills/luckiest-video-studio-cards/packs/01-paper-collage/cards/tier1/t1-stat-receipt.html +24 -12
- package/skills/luckiest-video-studio-cards/packs/01-paper-collage/cards/tier1/t1-stat-ribbon.html +34 -12
- package/skills/luckiest-video-studio-cards/packs/01-paper-collage/cards/tier1/t1-stat-semi.html +22 -7
- package/skills/luckiest-video-studio-cards/packs/01-paper-collage/cards/tier1/t1-stat-spotlight.html +23 -9
- package/skills/luckiest-video-studio-cards/packs/01-paper-collage/cards/tier1/t1-stat-stamp.html +24 -7
- package/skills/luckiest-video-studio-cards/packs/01-paper-collage/cards/tier1/t1-stat-steps.html +30 -9
- package/skills/luckiest-video-studio-cards/packs/01-paper-collage/cards/tier1/t1-stat-tape.html +33 -12
- package/skills/luckiest-video-studio-cards/packs/01-paper-collage/cards/tier1/t1-stat-torn.html +22 -9
- package/skills/luckiest-video-studio-cards/packs/01-paper-collage/cards/tier1/t1-stat-trend.html +23 -9
- package/skills/luckiest-video-studio-cards/packs/01-paper-collage/cards/tier1/t1-stat-vs.html +30 -10
- package/skills/luckiest-video-studio-cards/packs/01-paper-collage/cards/tier1/t1-stat-window.html +38 -25
- package/skills/luckiest-video-studio-cards/packs/01-paper-collage/cards/tier1/t1-stat.html +23 -4
- package/skills/luckiest-video-studio-cards/packs/01-paper-collage/cards/tier1/t1-timeline.html +41 -6
- package/skills/luckiest-video-studio-cards/packs/01-paper-collage/cards/tier2/t2-label.html +10 -3
- package/skills/luckiest-video-studio-cards/packs/01-paper-collage/cards/tier2/t2-lb-bracket.html +9 -2
- package/skills/luckiest-video-studio-cards/packs/01-paper-collage/cards/tier2/t2-lb-caption.html +12 -5
- package/skills/luckiest-video-studio-cards/packs/01-paper-collage/cards/tier2/t2-lb-circle.html +10 -3
- package/skills/luckiest-video-studio-cards/packs/01-paper-collage/cards/tier2/t2-lb-definition.html +10 -3
- package/skills/luckiest-video-studio-cards/packs/01-paper-collage/cards/tier2/t2-lb-footnote.html +11 -4
- package/skills/luckiest-video-studio-cards/packs/01-paper-collage/cards/tier2/t2-lb-magnify.html +9 -2
- package/skills/luckiest-video-studio-cards/packs/01-paper-collage/cards/tier2/t2-lb-pin.html +9 -2
- package/skills/luckiest-video-studio-cards/packs/01-paper-collage/cards/tier2/t2-lb-pullquote.html +10 -3
- package/skills/luckiest-video-studio-cards/packs/01-paper-collage/cards/tier2/t2-lb-spotlight.html +15 -2
- package/skills/luckiest-video-studio-cards/packs/01-paper-collage/cards/tier2/t2-lb-sticky.html +9 -2
- package/skills/luckiest-video-studio-cards/packs/01-paper-collage/cards/tier2/t2-lb-tag.html +10 -3
- package/skills/luckiest-video-studio-cards/packs/01-paper-collage/cards/tier2/t2-lb-underline.html +9 -2
- package/skills/luckiest-video-studio-cards/packs/01-paper-collage/cards/tier2/t2-lower-third.html +9 -2
- package/skills/luckiest-video-studio-cards/packs/01-paper-collage/cards/tier2/t2-lt-badge.html +10 -3
- package/skills/luckiest-video-studio-cards/packs/01-paper-collage/cards/tier2/t2-lt-barslab.html +26 -7
- package/skills/luckiest-video-studio-cards/packs/01-paper-collage/cards/tier2/t2-lt-bracket.html +9 -2
- package/skills/luckiest-video-studio-cards/packs/01-paper-collage/cards/tier2/t2-lt-clapper.html +9 -2
- package/skills/luckiest-video-studio-cards/packs/01-paper-collage/cards/tier2/t2-lt-highlight.html +9 -2
- package/skills/luckiest-video-studio-cards/packs/01-paper-collage/cards/tier2/t2-lt-indextab.html +10 -3
- package/skills/luckiest-video-studio-cards/packs/01-paper-collage/cards/tier2/t2-lt-rail.html +9 -2
- package/skills/luckiest-video-studio-cards/packs/01-paper-collage/cards/tier2/t2-lt-ribbon.html +9 -2
- package/skills/luckiest-video-studio-cards/packs/01-paper-collage/cards/tier2/t2-lt-stacked.html +9 -2
- package/skills/luckiest-video-studio-cards/packs/01-paper-collage/cards/tier2/t2-lt-stamp.html +9 -2
- package/skills/luckiest-video-studio-cards/packs/01-paper-collage/cards/tier2/t2-lt-sticky.html +9 -2
- package/skills/luckiest-video-studio-cards/packs/01-paper-collage/cards/tier2/t2-lt-typecard.html +9 -2
- package/skills/luckiest-video-studio-cards/packs/01-paper-collage/style.json +1 -1
- package/skills/luckiest-video-studio-cards/packs/01-paper-collage/tokens.css +18 -8
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-overview-agenda.html +23 -5
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-overview-beforeafter.html +30 -6
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-overview-bento.html +34 -8
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-overview-bigleft.html +28 -6
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-overview-callouts.html +36 -7
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-overview-cardrow5.html +17 -4
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-overview-checklist.html +11 -3
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-overview-cycle.html +30 -6
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-overview-dashboard.html +32 -5
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-overview-deck2.html +21 -5
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-overview-deck3.html +18 -4
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-overview-duallist.html +24 -4
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-overview-featurecompare.html +19 -5
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-overview-featuregrid.html +25 -4
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-overview-flashcards.html +22 -5
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-overview-flow.html +23 -4
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-overview-funnel.html +19 -5
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-overview-gantt.html +22 -6
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-overview-grid6.html +17 -4
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-overview-grid9.html +15 -4
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-overview-iconlist.html +18 -3
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-overview-journey.html +41 -6
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-overview-kpirow.html +24 -6
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-overview-layers.html +20 -5
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-overview-legend.html +19 -4
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-overview-levels.html +19 -5
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-overview-logowall.html +18 -6
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-overview-mappoints.html +18 -5
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-overview-matrix.html +24 -6
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-overview-milestones.html +38 -5
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-overview-mindmap.html +35 -12
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-overview-nested.html +13 -5
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-overview-network.html +76 -31
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-overview-notifs.html +21 -3
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-overview-numlist.html +16 -4
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-overview-orgchart.html +36 -16
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-overview-outline.html +17 -3
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-overview-phases.html +23 -5
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-overview-pipeline.html +25 -4
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-overview-pricing.html +36 -8
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-overview-profiles.html +20 -5
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-overview-proscons.html +21 -6
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-overview-pyramid.html +17 -4
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-overview-quad.html +13 -5
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-overview-quotegrid.html +19 -5
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-overview-ranked.html +19 -5
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-overview-roadmap.html +27 -5
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-overview-spectrum.html +29 -6
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-overview-split3.html +24 -5
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-overview-spotlightcard.html +34 -8
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-overview-statgrid.html +17 -5
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-overview-steps.html +25 -4
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-overview-summary.html +22 -5
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-overview-tiercompare.html +29 -6
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-overview-timeline.html +26 -5
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-overview-toc.html +15 -5
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-overview-tree.html +40 -15
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-overview-tricards.html +22 -4
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-overview-venn.html +34 -9
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-overview-vstable.html +24 -5
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-section-ascend.html +10 -4
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-section-aurora-bars.html +12 -4
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-section-beam.html +11 -4
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-section-boxed.html +26 -13
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-section-breath.html +14 -3
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-section-chaptercard.html +13 -4
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-section-column-light.html +17 -9
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-section-constellation.html +15 -6
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-section-countdown.html +10 -4
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-section-curtain.html +9 -3
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-section-dawn.html +13 -4
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-section-depth.html +18 -12
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-section-divider.html +10 -3
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-section-drift-grid.html +11 -4
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-section-duotone.html +16 -4
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-section-eclipse.html +11 -4
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-section-emblem.html +12 -5
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-section-flare-sweep.html +14 -6
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-section-glow-rule.html +22 -13
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-section-gradient-word.html +15 -5
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-section-gridfloor.html +16 -2
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-section-halo.html +16 -5
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-section-horizon.html +16 -4
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-section-index.html +25 -9
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-section-kinetic.html +10 -3
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-section-lensflare.html +10 -3
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-section-liquid.html +12 -5
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-section-marquee.html +34 -25
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-section-mesh.html +13 -4
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-section-monolith.html +9 -3
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-section-node-title.html +17 -1
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-section-numeral.html +13 -4
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-section-orb.html +12 -2
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-section-orbit.html +9 -1
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-section-particles.html +7 -1
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-section-pill.html +7 -1
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-section-portal.html +14 -2
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-section-prism.html +15 -2
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-section-question.html +14 -2
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-section-quoteopen.html +11 -2
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-section-reveal-mask.html +6 -1
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-section-ribbon.html +12 -1
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-section-ripple.html +8 -1
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-section-searchbar.html +15 -2
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-section-slab.html +9 -2
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-section-sphere-top.html +12 -3
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-section-split-reveal.html +24 -7
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-section-splitpanel.html +27 -4
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-section-spotlight-cone.html +16 -3
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-section-spotlight.html +10 -2
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-section-stack.html +17 -4
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-section-stacked-words.html +14 -3
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-section-starfield.html +7 -1
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-section-sweep.html +11 -2
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-section-tunnel.html +14 -4
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-section-type-scale.html +9 -2
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-section-typed.html +9 -2
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-section-underline-grow.html +13 -1
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-section-waveform.html +11 -2
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-section-wordmark.html +11 -3
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-stat-annot.html +22 -7
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-stat-beforeafter.html +23 -6
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-stat-bigpercent.html +10 -3
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-stat-bracketstat.html +13 -3
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-stat-bubble.html +7 -3
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-stat-cbars.html +8 -3
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-stat-clockface.html +8 -4
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-stat-column.html +12 -4
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-stat-compass.html +7 -3
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-stat-counterpill.html +11 -3
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-stat-curve.html +22 -10
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-stat-delta.html +13 -4
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-stat-dial.html +9 -3
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-stat-donut.html +15 -4
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-stat-dotgrid.html +14 -4
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-stat-figure.html +9 -3
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-stat-fillshape.html +11 -3
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-stat-fraction.html +11 -5
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-stat-funnel.html +24 -8
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-stat-growtharrow.html +18 -4
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-stat-heatcell.html +8 -3
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-stat-isotype.html +16 -4
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-stat-layered.html +10 -3
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-stat-mega.html +9 -3
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-stat-meter.html +9 -4
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-stat-milestone.html +9 -3
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-stat-money.html +16 -4
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-stat-multiplier.html +12 -4
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-stat-multiring.html +10 -3
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-stat-needle.html +10 -3
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-stat-nodes.html +50 -9
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-stat-odometer.html +9 -4
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-stat-orbitmoons.html +21 -8
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-stat-orbitstat.html +9 -3
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-stat-pair.html +18 -3
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-stat-percentile.html +11 -3
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-stat-pictobar.html +11 -4
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-stat-polar.html +12 -2
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-stat-quotestat.html +15 -5
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-stat-radialbars.html +18 -6
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-stat-range.html +12 -5
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-stat-rank.html +13 -5
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-stat-ratio.html +10 -5
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-stat-ring.html +10 -3
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-stat-risewall.html +18 -2
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-stat-score.html +11 -4
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-stat-segbar.html +9 -3
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-stat-semigauge.html +9 -4
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-stat-sparkline.html +9 -3
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-stat-spectrum.html +9 -2
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-stat-split.html +14 -4
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-stat-stackedbars.html +9 -4
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-stat-tickerstat.html +18 -5
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-stat-tiles.html +18 -4
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-stat-timer.html +14 -4
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-stat-trendline.html +18 -4
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-stat-underscore.html +9 -3
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-stat-versus.html +18 -5
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-stat-waffle.html +18 -4
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier1/t1-stat-waterfall.html +9 -4
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier2/t2-lb-badge.html +13 -4
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier2/t2-lb-brace.html +13 -4
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier2/t2-lb-bracket.html +13 -4
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier2/t2-lb-bubble.html +16 -4
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier2/t2-lb-byline.html +17 -5
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier2/t2-lb-callout.html +13 -4
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier2/t2-lb-category.html +14 -5
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier2/t2-lb-checkmark.html +13 -4
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier2/t2-lb-chipstat.html +13 -4
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier2/t2-lb-comparemini.html +14 -5
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier2/t2-lb-coord.html +26 -8
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier2/t2-lb-counter.html +17 -6
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier2/t2-lb-crosshair.html +18 -6
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier2/t2-lb-dashed.html +19 -5
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier2/t2-lb-definition.html +14 -5
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier2/t2-lb-deltachip.html +15 -6
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier2/t2-lb-eyebrow.html +14 -5
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier2/t2-lb-fact.html +14 -5
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier2/t2-lb-flag.html +20 -7
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier2/t2-lb-formula.html +17 -7
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier2/t2-lb-hash.html +17 -5
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier2/t2-lb-highlightbox.html +13 -4
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier2/t2-lb-iconchip.html +13 -4
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier2/t2-lb-info.html +14 -5
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier2/t2-lb-infocard.html +13 -4
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier2/t2-lb-keycap.html +13 -4
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier2/t2-lb-keyword.html +12 -3
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier2/t2-lb-leader.html +16 -5
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier2/t2-lb-legend.html +14 -5
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier2/t2-lb-measure.html +14 -5
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier2/t2-lb-meterchip.html +16 -7
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier2/t2-lb-metric.html +15 -6
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier2/t2-lb-micropie.html +15 -6
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier2/t2-lb-minibar.html +15 -6
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier2/t2-lb-node.html +28 -18
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier2/t2-lb-note.html +14 -5
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier2/t2-lb-numbercallout.html +18 -6
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier2/t2-lb-percent.html +15 -6
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier2/t2-lb-pointer.html +31 -22
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier2/t2-lb-price.html +20 -8
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier2/t2-lb-progress.html +15 -6
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier2/t2-lb-pulse.html +14 -5
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier2/t2-lb-qmark.html +15 -6
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier2/t2-lb-quote.html +16 -7
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier2/t2-lb-rating.html +14 -5
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier2/t2-lb-ribbon.html +19 -6
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier2/t2-lb-ringmark.html +27 -17
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier2/t2-lb-search.html +14 -5
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier2/t2-lb-sparkchip.html +15 -6
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier2/t2-lb-spec.html +25 -13
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier2/t2-lb-status.html +15 -6
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier2/t2-lb-step.html +16 -7
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier2/t2-lb-tag.html +14 -5
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier2/t2-lb-takeaway.html +13 -4
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier2/t2-lb-tcode.html +18 -6
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier2/t2-lb-timestamp.html +15 -6
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier2/t2-lb-toast.html +15 -6
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier2/t2-lb-tooltip.html +14 -5
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier2/t2-lb-underline.html +14 -5
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier2/t2-lb-warning.html +16 -7
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier2/t2-lt-avatar.html +12 -5
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier2/t2-lt-badgecard.html +12 -6
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier2/t2-lt-barslide.html +11 -5
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier2/t2-lt-bracket.html +20 -7
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier2/t2-lt-brandbar.html +13 -7
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier2/t2-lt-bug.html +12 -5
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier2/t2-lt-capsule.html +14 -5
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier2/t2-lt-chapterbar.html +12 -5
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier2/t2-lt-chip.html +11 -5
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier2/t2-lt-cinemastrip.html +20 -8
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier2/t2-lt-cite.html +12 -6
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier2/t2-lt-clockname.html +11 -5
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier2/t2-lt-coordbar.html +16 -6
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier2/t2-lt-corner.html +11 -5
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier2/t2-lt-cornerframe.html +16 -6
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier2/t2-lt-countbar.html +13 -7
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier2/t2-lt-dividername.html +26 -6
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier2/t2-lt-dotline.html +11 -5
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier2/t2-lt-doublecard.html +12 -6
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier2/t2-lt-dual.html +12 -6
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier2/t2-lt-edgebar.html +11 -5
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier2/t2-lt-flipcard.html +15 -5
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier2/t2-lt-geopin.html +11 -5
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier2/t2-lt-glasscard.html +11 -5
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier2/t2-lt-gradient.html +11 -5
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier2/t2-lt-gradientbar.html +12 -4
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier2/t2-lt-handlebar.html +11 -5
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier2/t2-lt-infochips.html +11 -5
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier2/t2-lt-lensbar.html +25 -12
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier2/t2-lt-live.html +12 -6
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier2/t2-lt-location.html +14 -6
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier2/t2-lt-logolock.html +14 -6
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier2/t2-lt-micname.html +14 -6
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier2/t2-lt-minicard.html +13 -5
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier2/t2-lt-minimal.html +13 -5
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier2/t2-lt-nameplate3d.html +13 -5
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier2/t2-lt-neonframe.html +14 -5
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier2/t2-lt-neonpill.html +13 -6
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier2/t2-lt-nowplaying.html +15 -7
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier2/t2-lt-orbitbadge.html +13 -5
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier2/t2-lt-pill.html +14 -6
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier2/t2-lt-portraitframe.html +14 -6
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier2/t2-lt-progressname.html +13 -5
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier2/t2-lt-quote.html +15 -7
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier2/t2-lt-ratingname.html +14 -6
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier2/t2-lt-ribbon.html +13 -5
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier2/t2-lt-sidebracket.html +13 -5
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier2/t2-lt-slidetab.html +15 -6
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier2/t2-lt-social.html +14 -6
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier2/t2-lt-spotlightname.html +14 -6
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier2/t2-lt-stacked.html +13 -5
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier2/t2-lt-statline.html +13 -5
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier2/t2-lt-tagrow.html +14 -5
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier2/t2-lt-thinstrip.html +18 -8
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier2/t2-lt-ticker.html +29 -7
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier2/t2-lt-titlebar.html +19 -5
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier2/t2-lt-trust.html +16 -8
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier2/t2-lt-typedname.html +13 -5
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier2/t2-lt-underbar.html +13 -5
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/cards/tier2/t2-lt-waveband.html +14 -6
- package/skills/luckiest-video-studio-cards/packs/02-aurora-glass/tokens.css +18 -8
- package/skills/luckiest-video-studio-cards/packs/_blueprint/cards/tier1/t1-stat.html +4 -2
- package/skills/luckiest-video-studio-cards/packs/_blueprint/cards/tier2/t2-list.html +5 -2
- package/skills/luckiest-video-studio-cards/packs/_blueprint/tokens.css +12 -4
- package/skills/luckiest-video-studio-cards/references/card-contract.md +15 -1
- package/skills/luckiest-video-studio-cards/scripts/qa-cards.mjs +14 -8
- package/skills/luckiest-video-studio-cards/templates/glass-popout/index.html +35 -11
- package/skills/luckiest-video-studio-cards/templates/glass-popout/meta.json +6 -1
- package/skills/luckiest-video-studio-cards/templates/graph-paper/index.html +15 -10
- package/skills/luckiest-video-studio-cards/templates/graph-paper/meta.json +7 -2
- package/skills/luckiest-video-studio-motion/ATTRIBUTION.md +4 -0
- package/skills/luckiest-video-studio-motion/CHANGELOG.md +9 -0
- package/skills/luckiest-video-studio-motion/SKILL.md +7 -3
- package/skills/luckiest-video-studio-motion/references/vocabulary.md +21 -0
- package/skills/luckiest-video-studio-motion/templates/spring.js +50 -0
- package/skills/luckiest-video-studio-motion/templates/spring.test.mjs +51 -0
- package/skills/luckiest-video-studio-recreate/ATTRIBUTION.md +2 -0
- package/skills/luckiest-video-studio-recreate/CHANGELOG.md +11 -0
- package/skills/luckiest-video-studio-recreate/SKILL.md +46 -7
- package/skills/luckiest-video-studio-reel/CHANGELOG.md +6 -0
- package/skills/luckiest-video-studio-reel/SKILL.md +9 -4
- package/skills/luckiest-video-studio-reel/templates/reel.html +36 -18
- package/skills/luckiest-video-studio-reference/CHANGELOG.md +4 -0
- package/skills/luckiest-video-studio-reference/SKILL.md +10 -3
- package/skills/luckiest-video-studio-review/ATTRIBUTION.md +4 -0
- package/skills/luckiest-video-watcher/ATTRIBUTION.md +37 -0
- package/skills/luckiest-video-watcher/CHANGELOG.md +90 -0
- package/skills/luckiest-video-watcher/LICENSE-claude-video +21 -0
- package/skills/luckiest-video-watcher/SKILL.md +201 -0
- package/skills/luckiest-video-watcher/references/watch-guide.md +159 -0
- package/skills/luckiest-video-watcher/scripts/config.py +174 -0
- package/skills/luckiest-video-watcher/scripts/download.py +207 -0
- package/skills/luckiest-video-watcher/scripts/frames.py +758 -0
- package/skills/luckiest-video-watcher/scripts/gemini.py +162 -0
- package/skills/luckiest-video-watcher/scripts/local_whisperx.py +147 -0
- package/skills/luckiest-video-watcher/scripts/runtime.py +35 -0
- package/skills/luckiest-video-watcher/scripts/setup.py +338 -0
- package/skills/luckiest-video-watcher/scripts/transcribe.py +113 -0
- package/skills/luckiest-video-watcher/scripts/watch.py +430 -0
- package/skills/luckiest-video-watcher/scripts/whisper.py +425 -0
|
@@ -0,0 +1,425 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Transcribe a video via local WhisperX or the Groq/OpenAI Whisper APIs.
|
|
3
|
+
|
|
4
|
+
Strategy: extract audio (mono 16kHz mp3, tiny payload), upload to whichever
|
|
5
|
+
API has a key. Returns segments in the same shape as transcribe.parse_vtt so
|
|
6
|
+
the rest of the pipeline (filter_range, format_transcript) doesn't care where
|
|
7
|
+
the transcript came from.
|
|
8
|
+
|
|
9
|
+
Pure stdlib — no `pip install groq` or `pip install openai` needed.
|
|
10
|
+
"""
|
|
11
|
+
from __future__ import annotations
|
|
12
|
+
|
|
13
|
+
import io
|
|
14
|
+
import json
|
|
15
|
+
import math
|
|
16
|
+
import mimetypes
|
|
17
|
+
import shutil
|
|
18
|
+
import ssl
|
|
19
|
+
import sys
|
|
20
|
+
import time
|
|
21
|
+
import urllib.error
|
|
22
|
+
import uuid
|
|
23
|
+
from pathlib import Path
|
|
24
|
+
from urllib.request import Request, urlopen
|
|
25
|
+
|
|
26
|
+
from config import load_api_key, ConfigError
|
|
27
|
+
from runtime import configure_stdio, run_text
|
|
28
|
+
from transcribe import Segments, normalize_segments
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
GROQ_ENDPOINT = "https://api.groq.com/openai/v1/audio/transcriptions"
|
|
32
|
+
GROQ_MODEL = "whisper-large-v3"
|
|
33
|
+
|
|
34
|
+
OPENAI_ENDPOINT = "https://api.openai.com/v1/audio/transcriptions"
|
|
35
|
+
OPENAI_MODEL = "whisper-1"
|
|
36
|
+
|
|
37
|
+
# Both Groq's free tier and OpenAI whisper-1 cap uploads at 25 MB. We target a
|
|
38
|
+
# margin under that so multipart framing overhead never pushes a chunk over.
|
|
39
|
+
MAX_UPLOAD_BYTES = 24_000_000
|
|
40
|
+
MAX_MULTIPART_BYTES = 25_000_000
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def plan_chunks(
|
|
44
|
+
total_seconds: float,
|
|
45
|
+
total_bytes: int,
|
|
46
|
+
max_bytes: int = MAX_UPLOAD_BYTES,
|
|
47
|
+
) -> list[tuple[float, float]]:
|
|
48
|
+
"""Split a duration into contiguous (offset, duration) chunks under max_bytes.
|
|
49
|
+
|
|
50
|
+
Size scales linearly with duration (constant-bitrate mono mp3), so an even
|
|
51
|
+
time split yields evenly-sized chunks. Returns a single full-length chunk
|
|
52
|
+
when the audio already fits.
|
|
53
|
+
"""
|
|
54
|
+
if not math.isfinite(total_seconds) or total_seconds < 0 or max_bytes <= 0 or total_bytes < 0:
|
|
55
|
+
raise SystemExit("Invalid audio chunk duration or byte budget")
|
|
56
|
+
if total_bytes > max_bytes and total_seconds <= 0:
|
|
57
|
+
raise SystemExit("Cannot split oversized audio with unknown duration")
|
|
58
|
+
if total_bytes <= max_bytes or total_seconds <= 0:
|
|
59
|
+
return [(0.0, total_seconds)]
|
|
60
|
+
|
|
61
|
+
n = math.ceil(total_bytes / max_bytes)
|
|
62
|
+
chunk = total_seconds / n
|
|
63
|
+
plan: list[tuple[float, float]] = []
|
|
64
|
+
for i in range(n):
|
|
65
|
+
offset = i * chunk
|
|
66
|
+
# The last chunk absorbs any rounding remainder so durations sum exactly.
|
|
67
|
+
duration = (total_seconds - offset) if i == n - 1 else chunk
|
|
68
|
+
plan.append((round(offset, 3), round(duration, 3)))
|
|
69
|
+
return plan
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def extract_audio(video_path: str, out_path: Path) -> Path:
|
|
73
|
+
"""Extract mono 16kHz 64kbps mp3 — ~480 kB/min, fits any Whisper limit."""
|
|
74
|
+
if shutil.which("ffmpeg") is None:
|
|
75
|
+
raise SystemExit("ffmpeg is not installed. Install with: brew install ffmpeg")
|
|
76
|
+
|
|
77
|
+
out_path.parent.mkdir(parents=True, exist_ok=True)
|
|
78
|
+
cmd = [
|
|
79
|
+
"ffmpeg",
|
|
80
|
+
"-hide_banner",
|
|
81
|
+
"-loglevel", "error",
|
|
82
|
+
"-y",
|
|
83
|
+
"-i", str(Path(video_path).resolve()),
|
|
84
|
+
"-vn",
|
|
85
|
+
"-acodec", "libmp3lame",
|
|
86
|
+
"-ar", "16000",
|
|
87
|
+
"-ac", "1",
|
|
88
|
+
"-b:a", "64k",
|
|
89
|
+
str(out_path.resolve()),
|
|
90
|
+
]
|
|
91
|
+
result = run_text(cmd)
|
|
92
|
+
if result.returncode != 0:
|
|
93
|
+
raise SystemExit(f"ffmpeg audio extraction failed: {result.stderr.strip()}")
|
|
94
|
+
if not out_path.exists() or out_path.stat().st_size == 0:
|
|
95
|
+
raise SystemExit("ffmpeg produced no audio — video may have no audio track")
|
|
96
|
+
return out_path
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
def audio_duration(audio_path: Path) -> float:
|
|
100
|
+
from frames import get_metadata
|
|
101
|
+
return get_metadata(str(audio_path))["duration_seconds"]
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
def split_audio(
|
|
105
|
+
full_audio: Path,
|
|
106
|
+
work_dir: Path,
|
|
107
|
+
plan: list[tuple[float, float]],
|
|
108
|
+
) -> list[tuple[Path, float]]:
|
|
109
|
+
"""Slice full_audio into per-plan chunk files, returning (path, offset) pairs.
|
|
110
|
+
|
|
111
|
+
Uses stream copy (`-c copy`) so there is no re-encode and no quality loss;
|
|
112
|
+
mp3 frame boundaries are close enough for transcription's purposes.
|
|
113
|
+
"""
|
|
114
|
+
if shutil.which("ffmpeg") is None:
|
|
115
|
+
raise SystemExit("ffmpeg is not installed. Install with: brew install ffmpeg")
|
|
116
|
+
|
|
117
|
+
work_dir.mkdir(parents=True, exist_ok=True)
|
|
118
|
+
chunks: list[tuple[Path, float]] = []
|
|
119
|
+
for index, (offset, duration) in enumerate(plan):
|
|
120
|
+
out_path = work_dir / f"chunk_{index:03d}.mp3"
|
|
121
|
+
cmd = [
|
|
122
|
+
"ffmpeg",
|
|
123
|
+
"-hide_banner",
|
|
124
|
+
"-loglevel", "error",
|
|
125
|
+
"-y",
|
|
126
|
+
"-ss", f"{offset:.3f}",
|
|
127
|
+
"-i", str(full_audio.resolve()),
|
|
128
|
+
"-t", f"{duration:.3f}",
|
|
129
|
+
"-c", "copy",
|
|
130
|
+
str(out_path.resolve()),
|
|
131
|
+
]
|
|
132
|
+
result = run_text(cmd)
|
|
133
|
+
if result.returncode != 0 or not out_path.exists() or out_path.stat().st_size == 0:
|
|
134
|
+
raise SystemExit(
|
|
135
|
+
f"ffmpeg failed to split audio chunk {index + 1}: {result.stderr.strip()}"
|
|
136
|
+
)
|
|
137
|
+
chunks.append((out_path, offset))
|
|
138
|
+
return chunks
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
def _build_multipart(fields: dict[str, str], file_path: Path) -> tuple[bytes, str]:
|
|
142
|
+
"""Assemble a multipart/form-data body the Whisper APIs accept.
|
|
143
|
+
|
|
144
|
+
Whisper's multipart upload is small and predictable — doing it by hand
|
|
145
|
+
keeps us on pure stdlib instead of pulling requests/groq/openai SDKs.
|
|
146
|
+
"""
|
|
147
|
+
boundary = f"----WatchBoundary{uuid.uuid4().hex}"
|
|
148
|
+
eol = b"\r\n"
|
|
149
|
+
buf = io.BytesIO()
|
|
150
|
+
|
|
151
|
+
for name, value in fields.items():
|
|
152
|
+
buf.write(f"--{boundary}".encode()); buf.write(eol)
|
|
153
|
+
buf.write(f'Content-Disposition: form-data; name="{name}"'.encode()); buf.write(eol)
|
|
154
|
+
buf.write(eol)
|
|
155
|
+
buf.write(str(value).encode()); buf.write(eol)
|
|
156
|
+
|
|
157
|
+
mimetype = mimetypes.guess_type(file_path.name)[0] or "application/octet-stream"
|
|
158
|
+
buf.write(f"--{boundary}".encode()); buf.write(eol)
|
|
159
|
+
buf.write(
|
|
160
|
+
f'Content-Disposition: form-data; name="file"; filename="{file_path.name}"'.encode()
|
|
161
|
+
)
|
|
162
|
+
buf.write(eol)
|
|
163
|
+
buf.write(f"Content-Type: {mimetype}".encode()); buf.write(eol)
|
|
164
|
+
buf.write(eol)
|
|
165
|
+
buf.write(file_path.read_bytes())
|
|
166
|
+
buf.write(eol)
|
|
167
|
+
buf.write(f"--{boundary}--".encode()); buf.write(eol)
|
|
168
|
+
|
|
169
|
+
return buf.getvalue(), boundary
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
MAX_ATTEMPTS = 4 # initial + 3 retries
|
|
173
|
+
MAX_429_RETRIES = 2
|
|
174
|
+
RETRY_BASE_DELAY = 2.0
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
def _post_whisper(endpoint: str, api_key: str, model: str, audio_path: Path) -> dict:
|
|
178
|
+
if audio_path.stat().st_size > MAX_UPLOAD_BYTES:
|
|
179
|
+
raise SystemExit("Audio file exceeds the 24,000,000-byte upload budget; split it before upload.")
|
|
180
|
+
fields = {
|
|
181
|
+
"model": model,
|
|
182
|
+
"response_format": "verbose_json",
|
|
183
|
+
"temperature": "0",
|
|
184
|
+
}
|
|
185
|
+
body, boundary = _build_multipart(fields, audio_path)
|
|
186
|
+
if len(body) > MAX_MULTIPART_BYTES:
|
|
187
|
+
raise SystemExit("Multipart request exceeds the 25,000,000-byte limit.")
|
|
188
|
+
headers = {
|
|
189
|
+
"Authorization": f"Bearer {api_key}",
|
|
190
|
+
"Content-Type": f"multipart/form-data; boundary={boundary}",
|
|
191
|
+
# Groq sits behind Cloudflare — the default `Python-urllib/3.x` UA
|
|
192
|
+
# trips WAF rule 1010 (403) before auth even runs. Any non-default
|
|
193
|
+
# UA clears it; we identify honestly.
|
|
194
|
+
"User-Agent": "watch-skill/1.0 (+claude-code; python-urllib)",
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
context = ssl.create_default_context()
|
|
198
|
+
rate_limit_hits = 0
|
|
199
|
+
last_exc: Exception | None = None
|
|
200
|
+
last_detail = ""
|
|
201
|
+
|
|
202
|
+
for attempt in range(MAX_ATTEMPTS):
|
|
203
|
+
request = Request(endpoint, data=body, headers=headers, method="POST")
|
|
204
|
+
try:
|
|
205
|
+
with urlopen(request, timeout=300, context=context) as response:
|
|
206
|
+
payload = response.read().decode("utf-8", errors="replace")
|
|
207
|
+
except urllib.error.HTTPError as exc:
|
|
208
|
+
detail = _read_error_body(exc)
|
|
209
|
+
last_exc, last_detail = exc, detail
|
|
210
|
+
|
|
211
|
+
# 4xx other than 429 are client errors — no retry will fix them.
|
|
212
|
+
if 400 <= exc.code < 500 and exc.code != 429:
|
|
213
|
+
raise SystemExit(f"Whisper request failed: {exc}{detail}")
|
|
214
|
+
|
|
215
|
+
if exc.code == 429:
|
|
216
|
+
rate_limit_hits += 1
|
|
217
|
+
if rate_limit_hits >= MAX_429_RETRIES:
|
|
218
|
+
raise SystemExit(f"Whisper request failed: {exc}{detail}")
|
|
219
|
+
delay = _retry_after(exc) or RETRY_BASE_DELAY * (2 ** attempt) + 1
|
|
220
|
+
else:
|
|
221
|
+
delay = RETRY_BASE_DELAY * (2 ** attempt)
|
|
222
|
+
|
|
223
|
+
if attempt < MAX_ATTEMPTS - 1:
|
|
224
|
+
print(
|
|
225
|
+
f"[watch] whisper HTTP {exc.code} — retrying in {delay:.1f}s "
|
|
226
|
+
f"(attempt {attempt + 2}/{MAX_ATTEMPTS})",
|
|
227
|
+
file=sys.stderr,
|
|
228
|
+
)
|
|
229
|
+
time.sleep(delay)
|
|
230
|
+
continue
|
|
231
|
+
except (urllib.error.URLError, TimeoutError, ConnectionResetError, OSError) as exc:
|
|
232
|
+
last_exc, last_detail = exc, ""
|
|
233
|
+
if attempt < MAX_ATTEMPTS - 1:
|
|
234
|
+
delay = RETRY_BASE_DELAY * (attempt + 1)
|
|
235
|
+
print(
|
|
236
|
+
f"[watch] whisper network error ({type(exc).__name__}: {exc}) — "
|
|
237
|
+
f"retrying in {delay:.1f}s (attempt {attempt + 2}/{MAX_ATTEMPTS})",
|
|
238
|
+
file=sys.stderr,
|
|
239
|
+
)
|
|
240
|
+
time.sleep(delay)
|
|
241
|
+
continue
|
|
242
|
+
|
|
243
|
+
try:
|
|
244
|
+
return json.loads(payload)
|
|
245
|
+
except json.JSONDecodeError as exc:
|
|
246
|
+
raise SystemExit(f"Whisper returned non-JSON response: {exc}")
|
|
247
|
+
|
|
248
|
+
raise SystemExit(
|
|
249
|
+
f"Whisper request failed after {MAX_ATTEMPTS} attempts: {last_exc}{last_detail}"
|
|
250
|
+
)
|
|
251
|
+
|
|
252
|
+
|
|
253
|
+
def _read_error_body(exc: urllib.error.HTTPError) -> str:
|
|
254
|
+
try:
|
|
255
|
+
body = exc.read()
|
|
256
|
+
except Exception:
|
|
257
|
+
return ""
|
|
258
|
+
if not body:
|
|
259
|
+
return ""
|
|
260
|
+
try:
|
|
261
|
+
return f" — {body.decode('utf-8', errors='replace')[:400]}"
|
|
262
|
+
except Exception:
|
|
263
|
+
return ""
|
|
264
|
+
|
|
265
|
+
|
|
266
|
+
def _retry_after(exc: urllib.error.HTTPError) -> float | None:
|
|
267
|
+
header = exc.headers.get("Retry-After") if getattr(exc, "headers", None) else None
|
|
268
|
+
if not header:
|
|
269
|
+
return None
|
|
270
|
+
try:
|
|
271
|
+
return float(header)
|
|
272
|
+
except ValueError:
|
|
273
|
+
return None
|
|
274
|
+
|
|
275
|
+
|
|
276
|
+
def shift_segments(segments: list[dict], offset_seconds: float) -> list[dict]:
|
|
277
|
+
"""Return a copy of segments with start/end shifted by offset_seconds.
|
|
278
|
+
|
|
279
|
+
Each chunk is transcribed in isolation, so Whisper returns 0-based timestamps
|
|
280
|
+
per chunk; shifting by the chunk's offset stitches them into source time.
|
|
281
|
+
"""
|
|
282
|
+
if offset_seconds == 0:
|
|
283
|
+
return segments
|
|
284
|
+
return [
|
|
285
|
+
{
|
|
286
|
+
"start": round(seg["start"] + offset_seconds, 2),
|
|
287
|
+
"end": round(seg["end"] + offset_seconds, 2),
|
|
288
|
+
"text": seg["text"],
|
|
289
|
+
}
|
|
290
|
+
for seg in segments
|
|
291
|
+
]
|
|
292
|
+
|
|
293
|
+
|
|
294
|
+
def _segments_from_response(data: dict) -> list[dict]:
|
|
295
|
+
try:
|
|
296
|
+
return normalize_segments(data)
|
|
297
|
+
except (ValueError, TypeError) as exc:
|
|
298
|
+
raise SystemExit(f"Whisper returned malformed segments: {exc}") from None
|
|
299
|
+
|
|
300
|
+
|
|
301
|
+
def transcribe_chunks(
|
|
302
|
+
chunks: list[tuple[Path, float]],
|
|
303
|
+
transcribe_one,
|
|
304
|
+
) -> list[dict]:
|
|
305
|
+
"""Transcribe each chunk, shift its segments by the chunk offset, concatenate.
|
|
306
|
+
|
|
307
|
+
A chunk that fails after its own retries is logged and skipped so one bad
|
|
308
|
+
slice doesn't discard the whole transcript. Raises only if every chunk fails.
|
|
309
|
+
"""
|
|
310
|
+
segments = Segments()
|
|
311
|
+
failures = 0
|
|
312
|
+
for index, (path, offset) in enumerate(chunks):
|
|
313
|
+
try:
|
|
314
|
+
chunk_segments = transcribe_one(path)
|
|
315
|
+
except SystemExit as exc:
|
|
316
|
+
failures += 1
|
|
317
|
+
end = chunks[index + 1][1] if index + 1 < len(chunks) else None
|
|
318
|
+
segments.gaps.append({"start": offset, "end": end})
|
|
319
|
+
print(
|
|
320
|
+
f"[watch] chunk {index + 1}/{len(chunks)} failed — skipping ({exc})",
|
|
321
|
+
file=sys.stderr,
|
|
322
|
+
)
|
|
323
|
+
continue
|
|
324
|
+
segments.extend(shift_segments(chunk_segments, offset))
|
|
325
|
+
print(
|
|
326
|
+
f"[watch] chunk {index + 1}/{len(chunks)} → {len(chunk_segments)} segments",
|
|
327
|
+
file=sys.stderr,
|
|
328
|
+
)
|
|
329
|
+
|
|
330
|
+
if failures == len(chunks):
|
|
331
|
+
raise SystemExit("Whisper failed on every audio chunk")
|
|
332
|
+
segments.no_speech = not segments and not failures
|
|
333
|
+
return segments
|
|
334
|
+
|
|
335
|
+
|
|
336
|
+
def _transcribe_file(backend: str, api_key: str, audio_path: Path) -> list[dict]:
|
|
337
|
+
"""Upload one audio file and return its 0-based segments."""
|
|
338
|
+
if backend == "groq":
|
|
339
|
+
response = _post_whisper(GROQ_ENDPOINT, api_key, GROQ_MODEL, audio_path)
|
|
340
|
+
elif backend == "openai":
|
|
341
|
+
response = _post_whisper(OPENAI_ENDPOINT, api_key, OPENAI_MODEL, audio_path)
|
|
342
|
+
else:
|
|
343
|
+
raise SystemExit(f"Unknown whisper backend: {backend}")
|
|
344
|
+
return _segments_from_response(response)
|
|
345
|
+
|
|
346
|
+
|
|
347
|
+
def transcribe_video(
|
|
348
|
+
video_path: str,
|
|
349
|
+
audio_out: Path,
|
|
350
|
+
backend: str | None = None,
|
|
351
|
+
api_key: str | None = None,
|
|
352
|
+
) -> tuple[list[dict], str]:
|
|
353
|
+
"""Run the full flow: extract audio → upload → parse segments.
|
|
354
|
+
|
|
355
|
+
Returns (segments, backend_used). Raises SystemExit on any failure.
|
|
356
|
+
"""
|
|
357
|
+
if api_key is not None and backend is None:
|
|
358
|
+
raise SystemExit("An API key requires an explicit groq or openai backend.")
|
|
359
|
+
if backend == "whisperx":
|
|
360
|
+
if api_key is not None:
|
|
361
|
+
raise SystemExit("WhisperX does not accept an API key.")
|
|
362
|
+
from local_whisperx import transcribe_audio
|
|
363
|
+
segments = transcribe_audio(extract_audio(video_path, audio_out))
|
|
364
|
+
return segments, "whisperx"
|
|
365
|
+
if backend not in (None, "groq", "openai"):
|
|
366
|
+
raise SystemExit("Unknown transcription backend.")
|
|
367
|
+
if backend is None or api_key is None:
|
|
368
|
+
detected_backend, detected_key = load_api_key(preferred=backend)
|
|
369
|
+
backend = backend or detected_backend
|
|
370
|
+
api_key = api_key or detected_key
|
|
371
|
+
|
|
372
|
+
if not backend or not api_key:
|
|
373
|
+
setup_py = Path(__file__).resolve().parent / "setup.py"
|
|
374
|
+
raise SystemExit(
|
|
375
|
+
"No Whisper API key available. Set GROQ_API_KEY (preferred) or OPENAI_API_KEY "
|
|
376
|
+
"in the environment or in ~/.config/watch/.env. "
|
|
377
|
+
f"Run `python3 {setup_py}` to configure."
|
|
378
|
+
)
|
|
379
|
+
|
|
380
|
+
print(f"[watch] extracting audio for Whisper ({backend})…", file=sys.stderr)
|
|
381
|
+
audio_path = extract_audio(video_path, audio_out)
|
|
382
|
+
audio_bytes = audio_path.stat().st_size
|
|
383
|
+
|
|
384
|
+
def transcribe_one(path: Path) -> list[dict]:
|
|
385
|
+
return _transcribe_file(backend, api_key, path)
|
|
386
|
+
|
|
387
|
+
if audio_bytes <= MAX_UPLOAD_BYTES:
|
|
388
|
+
print(
|
|
389
|
+
f"[watch] audio: {audio_bytes / 1024:.0f} kB — uploading to {backend} Whisper…",
|
|
390
|
+
file=sys.stderr,
|
|
391
|
+
)
|
|
392
|
+
segments = transcribe_one(audio_path)
|
|
393
|
+
else:
|
|
394
|
+
duration = audio_duration(audio_path)
|
|
395
|
+
plan = plan_chunks(duration, audio_bytes, MAX_UPLOAD_BYTES - 64_000)
|
|
396
|
+
print(
|
|
397
|
+
f"[watch] audio: {audio_bytes / (1024 * 1024):.0f} MB exceeds "
|
|
398
|
+
f"{MAX_UPLOAD_BYTES // (1024 * 1024)} MB — splitting into {len(plan)} chunks…",
|
|
399
|
+
file=sys.stderr,
|
|
400
|
+
)
|
|
401
|
+
chunks = split_audio(audio_path, audio_out.parent / "chunks", plan)
|
|
402
|
+
if any(path.stat().st_size > MAX_UPLOAD_BYTES for path, _ in chunks):
|
|
403
|
+
raise SystemExit("A split audio chunk exceeds the upload budget; no chunks were uploaded.")
|
|
404
|
+
segments = transcribe_chunks(chunks, transcribe_one)
|
|
405
|
+
|
|
406
|
+
if not segments:
|
|
407
|
+
print("[watch] Whisper detected no speech", file=sys.stderr)
|
|
408
|
+
|
|
409
|
+
print(f"[watch] transcribed {len(segments)} segments via {backend}", file=sys.stderr)
|
|
410
|
+
return segments, backend
|
|
411
|
+
|
|
412
|
+
|
|
413
|
+
if __name__ == "__main__":
|
|
414
|
+
import argparse
|
|
415
|
+
configure_stdio()
|
|
416
|
+
parser = argparse.ArgumentParser(description="Transcribe local media with the selected Whisper backend.")
|
|
417
|
+
parser.add_argument("video")
|
|
418
|
+
parser.add_argument("audio_out", nargs="?", default="audio.mp3", type=Path)
|
|
419
|
+
parser.add_argument("--backend", choices=["groq", "openai", "whisperx"])
|
|
420
|
+
args = parser.parse_args()
|
|
421
|
+
try:
|
|
422
|
+
segments, backend = transcribe_video(args.video, Path(args.audio_out), backend=args.backend)
|
|
423
|
+
except ConfigError as exc:
|
|
424
|
+
raise SystemExit(str(exc)) from None
|
|
425
|
+
print(json.dumps({"backend": backend, "segments": segments}, indent=2))
|