{"_id":"@arafat2020/kurenai","_rev":"11-887cbaf7df3388971a9c7bfa2606a20d","name":"@arafat2020/kurenai","dist-tags":{"latest":"2.2.0-beta.1"},"versions":{"1.0.0":{"name":"@arafat2020/kurenai","version":"1.0.0","keywords":["ffmpeg","dsl","compiler","video","pipeline","kurenai"],"author":{"name":"Arafat Mannan"},"license":"MIT","_id":"@arafat2020/kurenai@1.0.0","maintainers":[{"name":"arafat2020","email":"arafatmannan2019@gmail.com"}],"homepage":"https://github.com/arafat2020/kurenai#readme","bugs":{"url":"https://github.com/arafat2020/kurenai/issues"},"bin":{"kurenai":"dist/main.js"},"dist":{"shasum":"d2a95a2e4e86ffd2b06ce321355804122bbb29c2","tarball":"https://registry.npmjs.org/@arafat2020/kurenai/-/kurenai-1.0.0.tgz","fileCount":26,"integrity":"sha512-w9AtBiRbmu7JUPYt+Pqsar6X72X9OvBvF5y2e2LhxBhOvo9RCMlm2JJMVwxDPILL6sw6S/FUpPFhpRykdn1x9g==","signatures":[{"sig":"MEYCIQCHKG01vhUmbRa0X3e8A+6rxkXzK3hBb4a83z/enBhv7AIhALQMTBEVlON1xW7xBiYxKVlUHcIUUbI7U29dsSUINLhs","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":69785},"main":"./dist/main.js","types":"./dist/main.d.ts","gitHead":"40be3b4268104b23912d6763732c41de31fd6185","private":false,"scripts":{"test":"vitest","build":"tsc","start":"tsx src/main.ts","test:ui":"vitest --ui"},"_npmUser":{"name":"arafat2020","email":"arafatmannan2019@gmail.com"},"repository":{"url":"git+https://github.com/arafat2020/kurenai.git","type":"git"},"_npmVersion":"11.4.1","description":"A DSL compiler that converts human-readable video pipeline scripts into FFmpeg commands","directories":{},"_nodeVersion":"22.14.0","dependencies":{"g":"^2.0.1","commander":"^15.0.0"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.22.4","vitest":"^4.1.8","ts-node":"^10.9.2","@vitest/ui":"^4.1.8","typescript":"^6.0.3","@types/node":"^25.9.1"},"_npmOperationalInternal":{"tmp":"tmp/kurenai_1.0.0_1781671401286_0.7060610034579609","host":"s3://npm-registry-packages-npm-production"}},"1.0.1":{"name":"@arafat2020/kurenai","version":"1.0.1","keywords":["ffmpeg","dsl","compiler","video","pipeline"],"author":{"name":"Arafat Mannan"},"license":"MIT","_id":"@arafat2020/kurenai@1.0.1","maintainers":[{"name":"arafat2020","email":"arafatmannan2019@gmail.com"}],"homepage":"https://github.com/arafat2020/kurenai#readme","bugs":{"url":"https://github.com/arafat2020/kurenai/issues"},"bin":{"kurenai":"dist/main.js"},"dist":{"shasum":"3b8a3837313d143d7470ca1f72e23023b28d5a31","tarball":"https://registry.npmjs.org/@arafat2020/kurenai/-/kurenai-1.0.1.tgz","fileCount":26,"integrity":"sha512-kvHpkpGMVr9/PHRZC+VR1nMM5eHHH6P7aioQp5kKQWFUyK7FlhWCXcnh5Ic+C0tDl5XSAoZyiP+/9VmMY2OXAg==","signatures":[{"sig":"MEYCIQCxt12xgAilHwPvhLRWRxtKniPWS7d+ZNHwksg4HoIS6wIhAMvPsU1k9SrK/8um7ZeOZYwKc/NXsZD3DTsFj5X/3kRX","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":69762},"main":"./dist/main.js","types":"./dist/main.d.ts","gitHead":"ef83f58515a807336d08fcf6d248484215bec4ec","scripts":{"test":"vitest","build":"tsc","start":"tsx src/main.ts","test:ui":"vitest --ui"},"_npmUser":{"name":"arafat2020","email":"arafatmannan2019@gmail.com"},"repository":{"url":"git+https://github.com/arafat2020/kurenai.git","type":"git"},"_npmVersion":"11.4.1","description":"A DSL compiler that converts human-readable video pipeline scripts into FFmpeg commands","directories":{},"_nodeVersion":"22.14.0","dependencies":{"g":"^2.0.1","commander":"^15.0.0"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.22.4","vitest":"^4.1.8","ts-node":"^10.9.2","@vitest/ui":"^4.1.8","typescript":"^6.0.3","@types/node":"^25.9.1"},"_npmOperationalInternal":{"tmp":"tmp/kurenai_1.0.1_1781671854089_0.037097765972277985","host":"s3://npm-registry-packages-npm-production"}},"1.1.0":{"name":"@arafat2020/kurenai","version":"1.1.0","keywords":["ffmpeg","dsl","compiler","video","pipeline"],"author":{"name":"Arafat Mannan"},"license":"MIT","_id":"@arafat2020/kurenai@1.1.0","maintainers":[{"name":"arafat2020","email":"arafatmannan2019@gmail.com"}],"homepage":"https://github.com/arafat2020/kurenai#readme","bugs":{"url":"https://github.com/arafat2020/kurenai/issues"},"bin":{"kurenai":"dist/main.js"},"dist":{"shasum":"1019538e86de4d1596edcbd9e031562c84a66c77","tarball":"https://registry.npmjs.org/@arafat2020/kurenai/-/kurenai-1.1.0.tgz","fileCount":30,"integrity":"sha512-0T7LdXlUiYTUXkMCp7XxmvQpDYuMsJSCx87Bq18rU+Fbsw5dsAaZ0HQW8wuYUWv+z7bwVNFOlSC4OaDH/kV1WA==","signatures":[{"sig":"MEUCIQDPDrkFk1Bodv2Q1e763KySL899DDYJexhBY6qLMjhr8QIgPUllbWVS/txR1UeTwYAb/BAKuiJIjNmArEiuVMbeKk8=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":81151},"main":"./dist/main.js","types":"./dist/main.d.ts","gitHead":"a4440bdab2d6d32823ed0d34b79857cf8b3d0da7","scripts":{"test":"vitest","build":"tsc","start":"tsx src/main.ts","test:ui":"vitest --ui"},"_npmUser":{"name":"arafat2020","email":"arafatmannan2019@gmail.com"},"repository":{"url":"git+https://github.com/arafat2020/kurenai.git","type":"git"},"_npmVersion":"11.4.1","description":"A DSL compiler that converts human-readable video pipeline scripts into FFmpeg commands","directories":{},"_nodeVersion":"22.14.0","dependencies":{"g":"^2.0.1","commander":"^15.0.0"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.22.4","vitest":"^4.1.8","ts-node":"^10.9.2","@vitest/ui":"^4.1.8","typescript":"^6.0.3","@types/node":"^25.9.1"},"_npmOperationalInternal":{"tmp":"tmp/kurenai_1.1.0_1781684579773_0.8938646641653383","host":"s3://npm-registry-packages-npm-production"}},"1.2.0":{"name":"@arafat2020/kurenai","version":"1.2.0","keywords":["ffmpeg","dsl","compiler","video","pipeline"],"author":{"name":"Arafat Mannan"},"license":"MIT","_id":"@arafat2020/kurenai@1.2.0","maintainers":[{"name":"arafat2020","email":"arafatmannan2019@gmail.com"}],"homepage":"https://github.com/arafat2020/kurenai#readme","bugs":{"url":"https://github.com/arafat2020/kurenai/issues"},"bin":{"kurenai":"dist/main.js"},"dist":{"shasum":"108cb2cb5cf3f547889f586a9cbabca8e1968f48","tarball":"https://registry.npmjs.org/@arafat2020/kurenai/-/kurenai-1.2.0.tgz","fileCount":30,"integrity":"sha512-GcHpe2TI/pwhxinp7aJiO9bZGTV4CYCvE/wDKsEttaqYWOFBQBPycwwSRR++0gMWKPvF5J0ToDAZZ5A8rqORzA==","signatures":[{"sig":"MEUCIQDBcNf8vF7ACyvUlU1V7RI5fWXsQScOrLOm4F9vQGAaJQIge3OEe6gax03Qmvjx9bhY31az/txL/4//WRq6iuzQm50=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":86032},"main":"./dist/main.js","types":"./dist/main.d.ts","gitHead":"4c91c64c51e303d20ad16a8ede157d1ce98c270e","scripts":{"test":"vitest","build":"tsc","start":"tsx src/main.ts","test:ui":"vitest --ui"},"_npmUser":{"name":"arafat2020","email":"arafatmannan2019@gmail.com"},"repository":{"url":"git+https://github.com/arafat2020/kurenai.git","type":"git"},"_npmVersion":"11.4.1","description":"A DSL compiler that converts human-readable video pipeline scripts into FFmpeg commands","directories":{},"_nodeVersion":"22.14.0","dependencies":{"g":"^2.0.1","commander":"^15.0.0"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.22.4","vitest":"^4.1.8","ts-node":"^10.9.2","@vitest/ui":"^4.1.8","typescript":"^6.0.3","@types/node":"^25.9.1"},"_npmOperationalInternal":{"tmp":"tmp/kurenai_1.2.0_1781936457836_0.16120583957920598","host":"s3://npm-registry-packages-npm-production"}},"1.3.0":{"name":"@arafat2020/kurenai","version":"1.3.0","keywords":["ffmpeg","dsl","compiler","video","pipeline"],"author":{"name":"Arafat Mannan"},"license":"MIT","_id":"@arafat2020/kurenai@1.3.0","maintainers":[{"name":"arafat2020","email":"arafatmannan2019@gmail.com"}],"homepage":"https://github.com/arafat2020/kurenai#readme","bugs":{"url":"https://github.com/arafat2020/kurenai/issues"},"bin":{"kurenai":"dist/main.js"},"dist":{"shasum":"40380fdd51fecf3f15f4377411af25446921b3ad","tarball":"https://registry.npmjs.org/@arafat2020/kurenai/-/kurenai-1.3.0.tgz","fileCount":34,"integrity":"sha512-Hufc/v2qrqmvKNiNJlO9mGt5gZ6/McHiT7dMNEs7uJv32m3CRrcfz3NiguDFHICJ1r25KglBLMYK7TpoolrOxw==","signatures":[{"sig":"MEYCIQDeti133qeJvZHSMnKJqYPm/x1FZQEJJl3IoeRxktC0DAIhAOpg0QYTGLQ4bcdMdmq4PBkNk4YNSeqjWmUksKb3BaAS","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":105413},"main":"./dist/index.js","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.js"}},"gitHead":"9bd1fd0b4ff4a4327832f3a98ae36cda4082e53b","scripts":{"test":"vitest","build":"tsc","start":"tsx src/main.ts","test:ui":"vitest --ui"},"_npmUser":{"name":"arafat2020","email":"arafatmannan2019@gmail.com"},"repository":{"url":"git+https://github.com/arafat2020/kurenai.git","type":"git"},"_npmVersion":"11.4.1","description":"A DSL compiler that converts human-readable video pipeline scripts into FFmpeg commands","directories":{},"_nodeVersion":"22.14.0","dependencies":{"g":"^2.0.1","commander":"^15.0.0"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.22.4","vitest":"^4.1.8","ts-node":"^10.9.2","@vitest/ui":"^4.1.8","typescript":"^6.0.3","@types/node":"^25.9.1"},"_npmOperationalInternal":{"tmp":"tmp/kurenai_1.3.0_1782187431285_0.7696285889863452","host":"s3://npm-registry-packages-npm-production"}},"1.3.3":{"name":"@arafat2020/kurenai","version":"1.3.3","keywords":["ffmpeg","dsl","compiler","video","pipeline"],"author":{"name":"Arafat Mannan"},"license":"MIT","_id":"@arafat2020/kurenai@1.3.3","maintainers":[{"name":"arafat2020","email":"arafatmannan2019@gmail.com"}],"homepage":"https://github.com/arafat2020/kurenai#readme","bugs":{"url":"https://github.com/arafat2020/kurenai/issues"},"bin":{"kurenai":"dist/main.js"},"dist":{"shasum":"bc7a884a78623ac96270c87e094b90d75ce5b3d6","tarball":"https://registry.npmjs.org/@arafat2020/kurenai/-/kurenai-1.3.3.tgz","fileCount":34,"integrity":"sha512-EIBge5OlsJHirLYgfwzDGM5AhZHVzCjKtgeZNYOlHz+xK8HWIeHyYN+36mNXjTnpDM9zDdfWk4iJMK+V7o/TVA==","signatures":[{"sig":"MEUCIAe58Fp0H9duInGQKzcVlMijhs9JkCg0QKmXnveeZM6CAiEA/MMFcdj+Jp4pbJ4JQS/0pPSnTPJ6+nVAwat+beX+DiA=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@arafat2020%2fkurenai@1.3.3","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":105830},"main":"./dist/index.js","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.js"}},"gitHead":"27c6646f974d20064db8843bd49d0b5e30ca058f","scripts":{"test":"vitest","build":"tsc","start":"tsx src/main.ts","test:ui":"vitest --ui"},"_npmUser":{"name":"arafat2020","email":"arafatmannan2019@gmail.com"},"repository":{"url":"git+https://github.com/arafat2020/kurenai.git","type":"git"},"_npmVersion":"10.9.8","description":"A DSL compiler that converts human-readable video pipeline scripts into FFmpeg commands","directories":{},"_nodeVersion":"22.22.3","dependencies":{"g":"^2.0.1","commander":"^15.0.0"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.22.4","vitest":"^4.1.8","ts-node":"^10.9.2","@vitest/ui":"^4.1.8","typescript":"^6.0.3","@types/node":"^25.9.1"},"_npmOperationalInternal":{"tmp":"tmp/kurenai_1.3.3_1782277657901_0.7584004431448235","host":"s3://npm-registry-packages-npm-production"}},"1.4.0-beta.1":{"name":"@arafat2020/kurenai","version":"1.4.0-beta.1","keywords":["ffmpeg","dsl","compiler","video","pipeline"],"author":{"name":"Arafat Mannan"},"license":"MIT","_id":"@arafat2020/kurenai@1.4.0-beta.1","maintainers":[{"name":"arafat2020","email":"arafatmannan2019@gmail.com"}],"homepage":"https://github.com/arafat2020/kurenai#readme","bugs":{"url":"https://github.com/arafat2020/kurenai/issues"},"bin":{"kurenai":"dist/main.js"},"dist":{"shasum":"cebd81237a6cb0af3215c54a9e195428f682cd70","tarball":"https://registry.npmjs.org/@arafat2020/kurenai/-/kurenai-1.4.0-beta.1.tgz","fileCount":94,"integrity":"sha512-Ma6bCw92YBxDgahBv2C2KCpI28XYU3+7+aFdClImKx+yQEHzoDMHp75Z1KDw+JZFxDA9pvOp9drcINY5KYsUYg==","signatures":[{"sig":"MEQCIDSTlsbJYBYu3th5QKxOvX4tk8L8qIoky9lP7pf7KHy/AiAoJQX7y2nN12uhlll3VUYDIb6zptRwHKybVwGrCFu3hQ==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@arafat2020%2fkurenai@1.4.0-beta.1","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":179467},"main":"./dist/index.js","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.js"}},"gitHead":"135e5e2843920022faedf876e8d45fab5cbc102f","scripts":{"test":"vitest","build":"tsc","start":"tsx src/main.ts","test:ui":"vitest --ui"},"_npmUser":{"name":"arafat2020","email":"arafatmannan2019@gmail.com"},"repository":{"url":"git+https://github.com/arafat2020/kurenai.git","type":"git"},"_npmVersion":"10.9.8","description":"A DSL compiler that converts human-readable video pipeline scripts into FFmpeg commands","directories":{},"_nodeVersion":"22.23.0","dependencies":{"g":"^2.0.1","commander":"^15.0.0"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.22.4","vitest":"^4.1.8","ts-node":"^10.9.2","@vitest/ui":"^4.1.8","typescript":"^6.0.3","@types/node":"^25.9.1"},"_npmOperationalInternal":{"tmp":"tmp/kurenai_1.4.0-beta.1_1782712492632_0.236385861465511","host":"s3://npm-registry-packages-npm-production"}},"1.4.0-beta.2":{"name":"@arafat2020/kurenai","version":"1.4.0-beta.2","keywords":["ffmpeg","dsl","compiler","video","pipeline"],"author":{"name":"Arafat Mannan"},"license":"MIT","_id":"@arafat2020/kurenai@1.4.0-beta.2","maintainers":[{"name":"arafat2020","email":"arafatmannan2019@gmail.com"}],"homepage":"https://github.com/arafat2020/kurenai#readme","bugs":{"url":"https://github.com/arafat2020/kurenai/issues"},"bin":{"kurenai":"dist/main.js"},"dist":{"shasum":"caf075165e25ba1db8e3f27515e6ffc99b4d8760","tarball":"https://registry.npmjs.org/@arafat2020/kurenai/-/kurenai-1.4.0-beta.2.tgz","fileCount":94,"integrity":"sha512-+vMMcJPiUIXG2hK3Hg52WV6to7LY3qwlYfXCgpnVM54bxbL+tC/H7IS5rUmqnbvdRjbyN5PWjTYkfwa40bBbSA==","signatures":[{"sig":"MEYCIQC1qVekB838lKq8pHlbxQTSWtlPdLZxyAuVpki2YIIyKQIhALyYhYUayvHxWP0mVaOw/1zxNJYs6YcOpZ9VS3pRSodQ","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@arafat2020%2fkurenai@1.4.0-beta.2","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":179474},"main":"./dist/index.js","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.js"}},"gitHead":"f1ad97fab99fbbaab7bb85a5073c2f7b9a02d6f2","scripts":{"test":"vitest","build":"tsc","start":"tsx src/main.ts","test:ui":"vitest --ui"},"_npmUser":{"name":"arafat2020","email":"arafatmannan2019@gmail.com"},"repository":{"url":"git+https://github.com/arafat2020/kurenai.git","type":"git"},"_npmVersion":"10.9.8","description":"A DSL compiler that converts human-readable video pipeline scripts into FFmpeg commands","directories":{},"_nodeVersion":"22.23.0","dependencies":{"g":"^2.0.1","commander":"^15.0.0"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.22.4","vitest":"^4.1.8","ts-node":"^10.9.2","@vitest/ui":"^4.1.8","typescript":"^6.0.3","@types/node":"^25.9.1"},"_npmOperationalInternal":{"tmp":"tmp/kurenai_1.4.0-beta.2_1782721190420_0.3486424000067476","host":"s3://npm-registry-packages-npm-production"}},"2.0.0-beta.1":{"name":"@arafat2020/kurenai","version":"2.0.0-beta.1","keywords":["ffmpeg","dsl","compiler","video","pipeline"],"author":{"name":"Arafat Mannan"},"license":"MIT","_id":"@arafat2020/kurenai@2.0.0-beta.1","maintainers":[{"name":"arafat2020","email":"arafatmannan2019@gmail.com"}],"homepage":"https://github.com/arafat2020/kurenai#readme","bugs":{"url":"https://github.com/arafat2020/kurenai/issues"},"bin":{"kurenai":"dist/main.js"},"dist":{"shasum":"5cd0d5aebecd1307d4b0289652c81a533a2e8118","tarball":"https://registry.npmjs.org/@arafat2020/kurenai/-/kurenai-2.0.0-beta.1.tgz","fileCount":126,"integrity":"sha512-ZjAQ/xp3DZrbZV7QaLLe4v/cJHr6uFu8I1BacIHbBvmmjwLt/q+6+OQJjw0eXDtxdI/71irJo1j56xxgbP6kOg==","signatures":[{"sig":"MEUCIQCLkgfWTW4VeL+K0v42KeNYKlGrnYeUgs8HvPX4fJNjHAIgRtWCxg9k3ycjtWKoihgRQLSAg8J+IUwgkmi9JQ37x+M=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@arafat2020%2fkurenai@2.0.0-beta.1","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":262954},"main":"./dist/index.js","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.js"}},"gitHead":"4736b69b3ad51772b93d48d8fb5dd7487bd1a3c5","scripts":{"test":"vitest","build":"tsc","start":"tsx src/main.ts","test:ui":"vitest --ui"},"_npmUser":{"name":"arafat2020","email":"arafatmannan2019@gmail.com"},"repository":{"url":"git+https://github.com/arafat2020/kurenai.git","type":"git"},"_npmVersion":"10.9.8","description":"A DSL compiler that converts human-readable video pipeline scripts into FFmpeg commands","directories":{},"_nodeVersion":"22.23.1","dependencies":{"g":"^2.0.1","commander":"^15.0.0"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.22.4","vitest":"^4.1.8","ts-node":"^10.9.2","@vitest/ui":"^4.1.8","typescript":"^6.0.3","@types/node":"^25.9.1"},"_npmOperationalInternal":{"tmp":"tmp/kurenai_2.0.0-beta.1_1783306500521_0.8302131154146797","host":"s3://npm-registry-packages-npm-production"}},"2.0.0-beta.2":{"name":"@arafat2020/kurenai","version":"2.0.0-beta.2","keywords":["ffmpeg","dsl","compiler","video","pipeline"],"author":{"name":"Arafat Mannan"},"license":"MIT","_id":"@arafat2020/kurenai@2.0.0-beta.2","maintainers":[{"name":"arafat2020","email":"arafatmannan2019@gmail.com"}],"homepage":"https://github.com/arafat2020/kurenai#readme","bugs":{"url":"https://github.com/arafat2020/kurenai/issues"},"bin":{"kurenai":"dist/main.js"},"dist":{"shasum":"e4ad080772804dc3f915b808ec508957fb3bf6e8","tarball":"https://registry.npmjs.org/@arafat2020/kurenai/-/kurenai-2.0.0-beta.2.tgz","fileCount":126,"integrity":"sha512-62lMr32uTooz8KfxlhHsjnYG2SX6UK3TsjMiKEKhC9YF8jdVpC/ez+PQ6fgUXdKUtj9lS6W0Pv2ay2Sxgz9R8w==","signatures":[{"sig":"MEUCIFMUV/u+HG/udAQ1K6yKnt9JmsQyImY6yuwBl0erOHhhAiEA5XNQ0fxUwuvyuhyYQ70FxJS30JCy2oLzk3aIkPZ8Ldg=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@arafat2020%2fkurenai@2.0.0-beta.2","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":262954},"main":"./dist/index.js","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.js"}},"gitHead":"3c5820981cb5931974164f392ef4408b76542443","scripts":{"test":"vitest","build":"tsc","start":"tsx src/main.ts","test:ui":"vitest --ui"},"_npmUser":{"name":"arafat2020","email":"arafatmannan2019@gmail.com"},"repository":{"url":"git+https://github.com/arafat2020/kurenai.git","type":"git"},"_npmVersion":"10.9.8","description":"A DSL compiler that converts human-readable video pipeline scripts into FFmpeg commands","directories":{},"_nodeVersion":"22.23.1","dependencies":{"g":"^2.0.1","commander":"^15.0.0"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.22.4","vitest":"^4.1.8","ts-node":"^10.9.2","@vitest/ui":"^4.1.8","typescript":"^6.0.3","@types/node":"^25.9.1"},"_npmOperationalInternal":{"tmp":"tmp/kurenai_2.0.0-beta.2_1783495034063_0.9277417037795428","host":"s3://npm-registry-packages-npm-production"}},"2.2.0-beta.1":{"name":"@arafat2020/kurenai","version":"2.2.0-beta.1","description":"A DSL compiler that converts human-readable video pipeline scripts into FFmpeg commands","main":"./dist/index.js","types":"./dist/index.d.ts","exports":{".":{"import":"./dist/index.js","require":"./dist/index.js","types":"./dist/index.d.ts"},"./browser":{"import":"./dist/browser.js","require":"./dist/browser.js","types":"./dist/browser.d.ts"}},"scripts":{"build":"tsc","start":"tsx src/main.ts","test":"vitest","test:node":"vitest --project node","test:browser":"vitest --project browser","test:ui":"vitest --ui"},"keywords":["ffmpeg","dsl","compiler","video","pipeline"],"author":{"name":"Arafat Mannan"},"repository":{"type":"git","url":"git+https://github.com/arafat2020/kurenai.git"},"license":"MIT","devDependencies":{"@types/node":"^25.9.1","@vitest/browser":"^4.1.10","@vitest/browser-playwright":"^4.1.10","@vitest/ui":"^4.1.8","mp4-muxer":"^5.2.2","playwright":"^1.62.1","ts-node":"^10.9.2","tsx":"^4.22.4","typescript":"^6.0.3","vitest":"^4.1.8"},"dependencies":{"commander":"^15.0.0","g":"^2.0.1","mediabunny":"^1.52.3"},"bin":{"kurenai":"dist/main.js"},"_id":"@arafat2020/kurenai@2.2.0-beta.1","gitHead":"b0c35dffdd8a59b3eb95122029bbbb524c33a69c","bugs":{"url":"https://github.com/arafat2020/kurenai/issues"},"homepage":"https://github.com/arafat2020/kurenai#readme","_nodeVersion":"22.23.1","_npmVersion":"10.9.8","dist":{"integrity":"sha512-hPwdY6SYxWQtj/2HJu+WMGz5kI831cGI3SZmsZQMqWw45cY0aII20CeZpGTXT0eE+hrqSeJZwnX6F85koolJLA==","shasum":"8924eee6a9d07bb753e5457663a5e58280e73ce2","tarball":"https://registry.npmjs.org/@arafat2020/kurenai/-/kurenai-2.2.0-beta.1.tgz","fileCount":166,"unpackedSize":368893,"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@arafat2020%2fkurenai@2.2.0-beta.1","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCICuQkUU0of/GsbHwX3l9E/5fYm7yPfh2gjInWDuYq7W8AiEAlf3Osqsa/kG5GVzunfuDgqTUmqojBu4A5fmt2LOaML8="}]},"_npmUser":{"name":"arafat2020","email":"arafatmannan2019@gmail.com"},"directories":{},"maintainers":[{"name":"arafat2020","email":"arafatmannan2019@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/kurenai_2.2.0-beta.1_1786354217717_0.11457679488650574"},"_hasShrinkwrap":false}},"time":{"created":"2026-06-17T04:43:21.137Z","modified":"2026-08-10T09:30:18.177Z","1.0.0":"2026-06-17T04:43:21.423Z","1.0.1":"2026-06-17T04:50:54.227Z","1.1.0":"2026-06-17T08:22:59.919Z","1.2.0":"2026-06-20T06:20:57.966Z","1.3.0":"2026-06-23T04:03:51.470Z","1.3.3":"2026-06-24T05:07:38.031Z","1.4.0-beta.1":"2026-06-29T05:54:52.762Z","1.4.0-beta.2":"2026-06-29T08:19:50.549Z","2.0.0-beta.1":"2026-07-06T02:55:00.665Z","2.0.0-beta.2":"2026-07-08T07:17:14.186Z","2.2.0-beta.1":"2026-08-10T09:30:17.880Z"},"bugs":{"url":"https://github.com/arafat2020/kurenai/issues"},"author":{"name":"Arafat Mannan"},"license":"MIT","homepage":"https://github.com/arafat2020/kurenai#readme","keywords":["ffmpeg","dsl","compiler","video","pipeline"],"repository":{"type":"git","url":"git+https://github.com/arafat2020/kurenai.git"},"description":"A DSL compiler that converts human-readable video pipeline scripts into FFmpeg commands","maintainers":[{"name":"arafat2020","email":"arafatmannan2019@gmail.com"}],"readme":"# Kurenai\n\nKurenai is a lightweight Domain Specific Language (DSL) and compiler for generating FFmpeg commands.\n\nInstead of memorizing complex FFmpeg flags and filter graphs, you describe your media processing pipeline using a clean, human-readable syntax and let Kurenai generate the commands for you — whether you're processing video, audio, or both.\n\n---\n\n## Features\n\n* Human-readable DSL for video **and audio** processing\n* Generates valid FFmpeg commands\n* CLI and TypeScript API\n* Time-range (chunked) rendering support\n* Built-in semantic validation\n* **Audio-first support** — process podcasts, music, and audio files without any video\n* **Full audio block** — codec, bitrate, sample rate, channels, normalization, EQ, compression, reverb, fade in/out\n* **Audio-only inputs** — `.mp3` `.wav` `.aac` `.flac` `.ogg` `.m4a` `.opus` `.wma` `.aiff`\n* Profile system for reusable configurations\n* Watermark and thumbnail support\n* Video resizing and frame rate conversion\n* Codec and bitrate configuration\n* **V2 mode** — multi-source timelines, named clips, and audio volume mixing\n* Multi-stage compiler architecture (Lexer → Parser → Analyzer → Codegen)\n* **Target-Dispatch Architecture** — target `ffmpeg` for servers or `webcodecs` for client-side processing\n* **In-Browser Video Processing** — zero server-cost video encoding directly in the browser via WebCodecs & Mediabunny\n* **Pre-Flight Hardware Capability Check** — test client GPU/browser encoder support with `checkWebCodecsCapability()`\n* Detailed compilation diagnostics\n\n---\n\n## Installation\n\n### Global CLI\n\n```bash\nnpm install -g @arafat2020/kurenai\n```\n\n### Project Dependency\n\n```bash\nnpm install @arafat2020/kurenai\n```\n\n---\n\n## Requirements\n\nKurenai generates FFmpeg commands. To execute them you must have FFmpeg installed:\n\n```bash\nffmpeg -version\n```\n\n---\n\n# Quick Examples\n\n## Video Processing\n\n```kurenai\ninput \"input.mp4\"\n\nresize 1280x720\nfps 30\n\nencode h264 aac\nbitrate 3000k\n\nwatermark \"logo.png\" bottom-right\nthumbnail 5s\n\noutput \"output.mp4\"\n```\n\n**Generated:**\n\n```bash\nffmpeg -i input.mp4 \\\n  -vf \"scale=1280:720,fps=30\" \\\n  -c:v libx264 -c:a aac \\\n  -b:v 3000k \\\n  -i logo.png -filter_complex \"overlay=main_w-overlay_w-10:main_h-overlay_h-10\" \\\n  output.mp4\n\nffmpeg -i input.mp4 -ss 5 -frames:v 1 thumb.jpg\n```\n\n---\n\n## Audio-Only Processing\n\nNo video required. Pass an audio file as input and Kurenai will skip all video filters automatically.\n\n```kurenai\ninput \"podcast.mp3\"\n\naudio {\n  normalize -14 LUFS\n  codec aac\n  bitrate 192k\n}\n\noutput \"podcast_mastered.mp3\"\n```\n\n**Generated:**\n\n```bash\nffmpeg -i podcast.mp3 \\\n  -c:a aac \\\n  -b:a 192k \\\n  -af \"loudnorm=I=-14\" \\\n  podcast_mastered.mp3\n```\n\n---\n\n## Full Audio Block — Video with Advanced Audio\n\n```kurenai\ninput \"video.mp4\"\n\naudio {\n  codec aac\n  bitrate 192k\n  samplerate 48000\n  channels stereo\n  normalize -14 LUFS\n  eq {\n    bass +3db\n    mid  -1db\n    treble +2db\n  }\n  compress {\n    threshold -18db\n    ratio 4:1\n    attack 5ms\n    release 100ms\n  }\n  reverb subtle\n  fadein  2s\n  fadeout 3s\n}\n\noutput \"out.mp4\"\n```\n\n**Generated:**\n\n```bash\nffmpeg -i video.mp4 \\\n  -c:a aac -b:a 192k -ar 48000 -ac 2 \\\n  -af \"loudnorm=I=-14,\\\n       equalizer=f=100:width_type=o:width=2:g=3,\\\n       equalizer=f=1000:width_type=o:width=2:g=-1,\\\n       equalizer=f=10000:width_type=o:width=2:g=2,\\\n       acompressor=threshold=-18dB:ratio=4:attack=5:release=100,\\\n       aecho=0.8:0.8:20:0.1,\\\n       afade=t=in:st=0:d=2,\\\n       afade=t=out:st=99999:d=3\" \\\n  out.mp4\n```\n\n---\n\n# Kurenai V2 — Multi-Source Timeline Mode\n\nV2 extends the language with **named sources**, **time-ranged clips**, an **audio mix block**, and an **ordered timeline**. Enable V2 mode by placing `use v2` as the first line of your script.\n\nAll V1 keywords (`encode`, `bitrate`, `resize`, `fps`, `audio`, `watermark`, `thumbnail`, `output`, `profile`, `use`) remain fully supported and unchanged inside a V2 script.\n\n---\n\n## V2 Quick Example\n\n```kurenai\nuse v2\n\n# 1. Declare named input sources\nsource intro  \"intro.mp4\"\nsource main   \"main.mp4\"\nsource outro  \"outro.mp4\"\nsource music  \"background.mp3\"\nsource voice  \"voiceover.mp3\"\n\n# 2. Cut clips from sources\nclip c_intro from intro  0s to 10s\nclip c_main  from main   5s to 45s\nclip c_outro from outro  0s  to 8s\n\n# 3. Define an audio mix (multiple tracks with per-track volume)\nmix bg {\n  track music volume 0.3\n  track voice volume 1.0\n}\n\n# 4. Arrange clips into the final timeline\ntimeline {\n  c_intro\n  c_main\n  c_outro\n}\n\n# 5. Apply global settings (same as V1)\nencode  h264 aac\nbitrate 8000k\naudio   bg      # reference the mix by name\n\noutput \"final.mp4\"\n```\n\n**Generated commands:**\n\n```bash\n# Pass 1 — render each clip segment\nffmpeg -ss 0  -to 10 -i intro.mp4 -c:v libx264 -c:a aac -b:v 8000k segment_c_intro.mp4\nffmpeg -ss 5  -to 45 -i main.mp4  -c:v libx264 -c:a aac -b:v 8000k segment_c_main.mp4\nffmpeg -ss 0  -to 8  -i outro.mp4 -c:v libx264 -c:a aac -b:v 8000k segment_c_outro.mp4\n\n# Pass 2 — concatenate segments and mix audio  (write segments.txt first)\nffmpeg -f concat -safe 0 -i segments.txt \\\n  -i background.mp3 -i voiceover.mp3 \\\n  -filter_complex \"[1:a]volume=0.3[music];[2:a]volume=1[voice];[music][voice]amix=inputs=2:duration=longest[aout]\" \\\n  -map 0:v -c:v copy -map [aout] -c:a aac \\\n  final.mp4\n```\n\n---\n\n# In-Browser Video Processing (WebCodecs)\n\nKurenai can compile `.crn` scripts into structured execution plans (`WebCodecsPipelinePlan`) that execute **directly inside the browser** using WebCodecs & [Mediabunny](https://github.com/mediabunny).\n\n### Benefits\n- **Zero Server Cost**: Client GPU/CPU renders the video.\n- **Privacy First**: Video files never leave the user's browser.\n- **Instant Start**: No multi-gigabyte uploads to cloud servers.\n\n### Basic Browser Example\n\n```ts\nimport { compileTarget } from \"@arafat2020/kurenai\";\nimport {\n  checkWebCodecsCapability,\n  executeWebCodecsPipeline,\n} from \"@arafat2020/kurenai/browser\";\n\n// 1. Compile script (auto-detects 'browser' -> target: 'webcodecs')\nconst result = compileTarget(`\n  input \"user_video.mp4\"\n  resize 1280x720\n  fps 30\n  encode h264 aac\n  bitrate 2.5M\n  output \"output.mp4\"\n`);\n\nif (result.target === \"webcodecs\") {\n  // 2. Pre-flight hardware encoder capability check\n  const cap = await checkWebCodecsCapability(result.plan);\n  if (!cap.supported) {\n    console.warn(\"Hardware encoder unsupported:\", cap.reason);\n    return fallbackToServer(result.plan);\n  }\n\n  // 3. Execute in-browser conversion\n  const [output] = await executeWebCodecsPipeline(\n    result.plan,\n    inputFile, // File | Blob from <input type=\"file\">\n    ({ ratio }) => console.log(`Progress: ${(ratio * 100).toFixed(0)}%`)\n  );\n\n  // output.data is Uint8Array video bytes\n  const blob = new Blob([output.data], { type: \"video/mp4\" });\n  videoElem.src = URL.createObjectURL(blob);\n}\n```\n\nFor React/Vue integration examples, memory optimization, and compatibility matrices, see the complete [**Frontend Integration Guide**](docs/FRONTEND_GUIDE.md).\n\n---\n\n## V2 Language Reference\n\n### `use v2`\n\nMust be the **first line** of the script. Activates the V2 parser and code generator.\n\n```kurenai\nuse v2\n```\n\n---\n\n### `source`\n\nDeclares a named input file. The name is used by `clip` and `mix` statements.\n\n```\nsource NAME \"file.ext\"\n```\n\n```kurenai\nsource intro \"intro.mp4\"\nsource music \"background.mp3\"\n```\n\nSupported video formats: `.mp4` `.avi` `.mkv` `.mov` `.flv` `.wmv` `.webm` `.mpeg` `.mpg` `.m4v`\n\nSupported audio formats: `.mp3` `.wav` `.aac` `.flac` `.ogg` `.m4a` `.opus` `.wma` `.aiff`\n\n---\n\n### `clip`\n\nCuts a time range from a named source and assigns it a clip name.\n\n```\nclip NAME from SOURCE STARTs to ENDs\n```\n\n```kurenai\nclip c_intro from intro 0s  to 10s\nclip c_main  from main  5s  to 45s\nclip c_outro from outro 0s  to 8s\n```\n\n| Part | Type | Description |\n|---|---|---|\n| `NAME` | identifier | Unique name for this clip |\n| `SOURCE` | identifier | Name of a declared `source` |\n| `START` / `END` | time (e.g. `5s`) | Start and end timestamps |\n\n---\n\n### `mix`\n\nDefines a named audio mix containing one or more tracks, each with an independent volume multiplier.\n\n```\nmix NAME {\n  track SOURCE volume N.NN\n  ...\n}\n```\n\n```kurenai\nmix bg {\n  track music volume 0.3   # 30% volume\n  track voice volume 1.0   # full volume\n}\n```\n\n| Part | Type | Description |\n|---|---|---|\n| `NAME` | identifier | Unique name for this mix |\n| `SOURCE` | identifier | Name of a declared `source` |\n| `N.NN` | float | Volume multiplier (e.g. `0.3`, `1.0`) |\n\nReference a mix in the `audio` keyword by its name:\n\n```kurenai\naudio bg\n```\n\n---\n\n### `timeline`\n\nDeclares the ordered sequence of clips that will be concatenated into the final output.\n\n```\ntimeline {\n  CLIP_NAME\n  CLIP_NAME\n  ...\n}\n```\n\n```kurenai\ntimeline {\n  c_intro\n  c_main\n  c_outro\n}\n```\n\n---\n\n## V2 Code Generation — Two-Pass Strategy\n\n| Pass | What it does |\n|---|---|\n| **Pass 1** | One `ffmpeg -ss … -to … -i SOURCE` command per clip in timeline order, producing `segment_CLIP.mp4` files |\n| **Pass 2** | One `ffmpeg -f concat` command per `output` statement; audio tracks from a `mix` block are composed via `-filter_complex amix` |\n| **Pass 3** | Optional `ffmpeg -ss … -frames:v 1` thumbnail extraction from the first output |\n\n---\n\n## V2 Semantic Rules\n\nThe analyzer enforces these rules and throws a `CompilerError` on any violation:\n\n| Rule | Error message |\n|---|---|\n| At least one `source` declared | \"At least one source is required.\" |\n| At least one `output` declared | \"Output file is missing.\" |\n| `timeline` present when clips are defined | \"Timeline is required when clips are defined.\" |\n| Source file format is supported | \"Unsupported source format: …\" |\n| `clip` references a declared `source` | `Clip \"X\" references unknown source \"Y\"` |\n| Clip cannot reference itself as source | `Clip \"X\" cannot reference itself as a source` |\n| Clip `start` < `end` | `Clip \"X\" start must be less than end` |\n| Mix `track` references a declared `source` | `Track in mix \"X\" references unknown source \"Y\"` |\n| `timeline` references declared clips only | `Timeline references unknown clip \"X\"` |\n| `audio NAME` references a declared mix | `Audio mix \"X\" not found` |\n\n---\n\n# CLI Usage\n\n## Validate\n\nRuns Lexing → Parsing → Semantic Analysis without generating commands.\n\n```bash\nkurenai validate pipeline.crn\n```\n\n---\n\n## Compile\n\nGenerates FFmpeg commands.\n\n```bash\nkurenai compile pipeline.crn\n```\n\nVerbose mode:\n\n```bash\nkurenai compile pipeline.crn --verbose\n```\n\nExample output:\n\n```text\n[1/4] Lexing...\n      ✓ 25 tokens\n\n[2/4] Parsing...\n      ✓ AST built\n\n[3/4] Analyzing...\n      ✓ Valid\n\n[4/4] Generating...\n      ✓ Done\n```\n\n---\n\n## Explain\n\nPrints a human-readable breakdown of the compilation result.\n\n```bash\nkurenai explain pipeline.crn\n```\n\nV2 output example:\n\n```text\nSources:\n  ✓ intro: intro.mp4\n  ✓ music: background.mp3\n\nClips:\n  ✓ c_intro from intro (0s to 10s)\n\nMixes:\n  ✓ bg: [music (vol: 0.3), voice (vol: 1)]\n\nTimeline:\n  ✓ c_intro → c_main → c_outro\n\nEncoding:\n  ✓ video codec: h264 → libx264\n  ✓ audio codec: aac\n```\n\n---\n\n## Run\n\nCompiles and executes generated FFmpeg commands.\n\n```bash\nkurenai run pipeline.crn\n```\n\n---\n\n# Language Reference (V1)\n\n---\n\n## `input`\n\n```kurenai\ninput \"video.mp4\"\ninput \"podcast.mp3\"\n```\n\nSupported video formats: `.mp4` `.avi` `.mkv` `.mov` `.flv` `.wmv` `.webm` `.mpeg` `.mpg` `.m4v`\n\nSupported audio formats: `.mp3` `.wav` `.aac` `.flac` `.ogg` `.m4a` `.opus` `.wma` `.aiff`\n\n---\n\n## `output`\n\n```kurenai\noutput \"final.mp4\"\n```\n\nMultiple outputs with per-output overrides:\n\n```kurenai\noutput \"youtube.mp4\"  { resize 1920x1080 }\noutput \"mobile.mp4\"   { resize 720x1280  }\n```\n\nSupported video formats: `.mp4` `.avi` `.mkv` `.mov` `.flv` `.wmv` `.webm` `.mpeg` `.mpg` `.m4v`\n\nSupported audio formats: `.mp3` `.wav` `.aac` `.flac` `.ogg` `.m4a` `.opus` `.wma` `.aiff`\n\n---\n\n## `audio` — Audio Block\n\nThe `audio` block configures all audio processing in one place. Every property is optional; include only what you need.\n\n```kurenai\naudio {\n  file       \"bg_music.mp3\"   # mix in an external audio track\n  codec      aac\n  bitrate    192k\n  samplerate 48000\n  channels   stereo           # stereo | mono\n\n  normalize -14 LUFS          # LUFS | dbtp | dbrms\n\n  eq {\n    bass   +3db\n    mid    -1db\n    treble +2db\n  }\n\n  compress {\n    threshold -18db\n    ratio     4:1\n    attack    5ms\n    release   100ms\n  }\n\n  reverb  subtle              # subtle | medium | large\n  fadein  2s\n  fadeout 3s\n}\n```\n\n### Audio Properties\n\n| Property | Values | FFmpeg mapping |\n|----------|--------|----------------|\n| `file` | `\"path.mp3\"` | `-i path.mp3` + `amix` |\n| `codec` | `aac` `mp3` `opus` `vorbis` | `-c:a` |\n| `bitrate` | `128k` `192k` `320k` … | `-b:a` |\n| `samplerate` | `44100` `48000` … | `-ar` |\n| `channels` | `stereo` `mono` | `-ac 2` / `-ac 1` |\n| `normalize` | `-14 LUFS` `-1 dbtp` `7 dbrms` | `loudnorm` filter |\n| `eq.bass` | `+3db` `-3db` … | `equalizer f=100` |\n| `eq.mid` | `+3db` `-3db` … | `equalizer f=1000` |\n| `eq.treble` | `+3db` `-3db` … | `equalizer f=10000` |\n| `compress.threshold` | `-18db` … | `acompressor threshold=` |\n| `compress.ratio` | `4:1` `8` … | `acompressor ratio=` |\n| `compress.attack` | `5ms` `10` … | `acompressor attack=` |\n| `compress.release` | `100ms` `200` … | `acompressor release=` |\n| `reverb` | `subtle` `medium` `large` | `aecho` filter |\n| `fadein` | `2s` `500ms` | `afade t=in` |\n| `fadeout` | `3s` `500ms` | `afade t=out` |\n\n---\n\n## `resize`\n\n```kurenai\nresize 1920x1080\n```\n\nScales the video. Width and height must each be divisible by 2. Ignored automatically when the input is an audio file.\n\n---\n\n## `fps`\n\n```kurenai\nfps 60\n```\n\nChanges frame rate. Allowed range: `1 – 240`. Ignored automatically when the input is an audio file.\n\n---\n\n## `encode`\n\n```kurenai\nencode h264 aac\n```\n\nSupported video codecs:\n\n```text\nh264  h265  vp8  vp9  av1  mpeg2video  theora\n```\n\nSupported audio codecs:\n\n```text\naac  mp3  opus  vorbis\n```\n\n---\n\n## `bitrate`\n\n```kurenai\nbitrate 5000k\n```\n\nSets video bitrate (use the `audio` block for audio bitrate).\n\n---\n\n## `watermark`\n\n```kurenai\nwatermark \"logo.png\" bottom-right\n```\n\nSupported positions:\n\n```text\ntop-left  top-right  bottom-left  bottom-right  center\n```\n\n---\n\n## `thumbnail`\n\n```kurenai\nthumbnail 10s\n```\n\nGenerates an additional FFmpeg command that extracts a frame at the specified timestamp.\n\n---\n\n# Profiles\n\nProfiles allow reusable encoding configurations.\n\n---\n\n## Define a Profile\n\n```kurenai\nprofile youtube_1080p {\n    resize 1920x1080\n    fps 60\n    encode h264 aac\n}\n```\n\n---\n\n## Use a Profile\n\n```kurenai\nuse youtube_1080p\n\ninput \"video.mp4\"\noutput \"output.mp4\"\n```\n\n---\n\n## Override Profile Values\n\nInline values always take precedence over profile defaults.\n\n```kurenai\nuse youtube_1080p\n\nfps 30\n\ninput \"video.mp4\"\noutput \"output.mp4\"\n```\n\nResult: Resolution `1920x1080`, FPS `30`, Codec `h264`.\n\n---\n\n# TypeScript API\n\n---\n\n## Compile (V1)\n\n```ts\nimport { compile } from \"@arafat2020/kurenai\";\n\nconst { commands } = compile(`\n  input \"podcast.mp3\"\n\n  audio {\n    normalize -14 LUFS\n    codec aac\n    bitrate 192k\n  }\n\n  output \"podcast_mastered.mp3\"\n`);\n\n// commands[0] → 'ffmpeg -i podcast.mp3 -c:a aac -b:a 192k -af \"loudnorm=I=-14\" podcast_mastered.mp3'\n```\n\n---\n\n## Compile (V2)\n\n```ts\nimport { compile, type ProgramV2 } from \"@arafat2020/kurenai\";\n\nconst { ast, commands } = compile(`\n  use v2\n\n  source intro \"intro.mp4\"\n  source music \"bg.mp3\"\n\n  clip c_intro from intro 0s to 10s\n\n  mix bg {\n    track music volume 0.5\n  }\n\n  timeline { c_intro }\n\n  encode h264 aac\n  audio  bg\n  output \"final.mp4\"\n`);\n\nconst v2 = ast as ProgramV2;\nconsole.log(Object.keys(v2.sources));  // ['intro', 'music']\nconsole.log(v2.timeline?.clips);       // ['c_intro']\nconsole.log(commands);                 // Pass-1 + Pass-2 FFmpeg commands\n```\n\n---\n\n## Target-Dispatch Compile (`compileTarget`)\n\n`compileTarget()` auto-detects the runtime environment or accepts an explicit `{ target }` option:\n\n```ts\nimport { compileTarget, type CompileOutput } from \"@arafat2020/kurenai\";\n\n// 1. Auto-detect environment ('node' -> 'ffmpeg', 'browser' -> 'webcodecs')\nconst result = compileTarget(source);\n\n// 2. Or pass an explicit target\nconst ffmpegResult = compileTarget(source, { target: \"ffmpeg\" });\nconst webcodecsResult = compileTarget(source, { target: \"webcodecs\" });\n\nif (result.target === \"ffmpeg\") {\n  console.log(result.commands); // string[]\n} else {\n  console.log(result.plan);     // WebCodecsPipelinePlan\n}\n```\n\n---\n\n## Browser Subpath Export (`@arafat2020/kurenai/browser`)\n\nImport browser-specific WebCodecs tools without bloating Node.js server bundles:\n\n```ts\nimport {\n  checkWebCodecsCapability,\n  executeWebCodecsPipeline,\n  detectEnvironment,\n  resolveTarget,\n} from \"@arafat2020/kurenai/browser\";\n```\n\n---\n\n## Individual Pipeline Stages\n\n```ts\nimport { lex, parse, analyzeAst, generateCommands } from \"@arafat2020/kurenai\";\n\nconst tokens   = lex(source);\nconst ast      = parse(tokens);       // returns Program | ProgramV2\nanalyzeAst(ast);                      // throws CompilerError on failure\nconst commands = generateCommands(ast);\n```\n\n---\n\n## Kurenai Class\n\n```ts\nimport { Kurenai } from \"@arafat2020/kurenai\";\n\nconst k = new Kurenai();\n\n// Full pipeline\nconst { commands } = k.compile(source);\n\n// Validate only (no codegen)\nk.validate(source);\n\n// Human-readable breakdown to stdout (works for both V1 and V2)\nk.explain(source);\n\n// Compile + execute FFmpeg (Node.js only)\nk.run(source);\n```\n\nThrows a `CompilerError` if validation fails.\n\n---\n\n# Compiler Pipeline\n\n```text\nSource (.crn)\n    ↓\n  Lexer           — tokenises keywords, strings, numbers, time, dB, floats, etc.\n    ↓\n  Parser          — builds a typed AST\n    ↓               V1: Program    (src/core/*Parser.ts)\n    ↓               V2: ProgramV2  (src/core/SourceParser, ClipParser,\n    ↓                               MixParser, TimelineParser  + all V1 parsers)\n  Analyzer        — validates formats, dimensions, codecs, FPS range,\n    ↓               clip references, time ranges, mix track sources\n  Code Generator  — translates AST nodes to FFmpeg flag sequences\n    ↓               V2: two-pass strategy (clip segments → concat + amix)\nFFmpeg Commands\n```\n\n---\n\n# Error Handling\n\nAll compilation errors throw a `CompilerError` with `message`, `line`, `column`, and `length` properties.\n\n```ts\nimport { compile, CompilerError } from \"@arafat2020/kurenai\";\n\ntry {\n  compile(source);\n} catch (err) {\n  if (err instanceof CompilerError) {\n    console.error(`Error at line ${err.line}: ${err.message}`);\n  }\n}\n```\n\nThe CLI displays the error with an underline pointing to the exact token:\n\n```text\nError on line 3:\n  clip c_intro from unknown 0s to 10s\n                    ^^^^^^^\n  Clip \"c_intro\" references unknown source \"unknown\"\n```\n\n---\n\n# License\n\nMIT License.\n","readmeFilename":"README.md"}