Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
175 changes: 175 additions & 0 deletions examples/bible-audiobook/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
# Based on https://raw.githubusercontent.com/github/gitignore/main/Node.gitignore

# Logs

logs
_.log
npm-debug.log_
yarn-debug.log*
yarn-error.log*
lerna-debug.log*
.pnpm-debug.log*

# Caches

.cache

# Diagnostic reports (https://nodejs.org/api/report.html)

report.[0-9]_.[0-9]_.[0-9]_.[0-9]_.json

# Runtime data

pids
_.pid
_.seed
*.pid.lock

# Directory for instrumented libs generated by jscoverage/JSCover

lib-cov

# Coverage directory used by tools like istanbul

coverage
*.lcov

# nyc test coverage

.nyc_output

# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)

.grunt

# Bower dependency directory (https://bower.io/)

bower_components

# node-waf configuration

.lock-wscript

# Compiled binary addons (https://nodejs.org/api/addons.html)

build/Release

# Dependency directories

node_modules/
jspm_packages/

# Snowpack dependency directory (https://snowpack.dev/)

web_modules/

# TypeScript cache

*.tsbuildinfo

# Optional npm cache directory

.npm

# Optional eslint cache

.eslintcache

# Optional stylelint cache

.stylelintcache

# Microbundle cache

.rpt2_cache/
.rts2_cache_cjs/
.rts2_cache_es/
.rts2_cache_umd/

# Optional REPL history

.node_repl_history

# Output of 'npm pack'

*.tgz

# Yarn Integrity file

.yarn-integrity

# dotenv environment variable files

.env
.env.development.local
.env.test.local
.env.production.local
.env.local

# parcel-bundler cache (https://parceljs.org/)

.parcel-cache

# Next.js build output

.next
out

# Nuxt.js build / generate output

.nuxt
dist

# Gatsby files

# Comment in the public line in if your project uses Gatsby and not Next.js

# https://nextjs.org/blog/next-9-1#public-directory-support

# public

# vuepress build output

.vuepress/dist

# vuepress v2.x temp and cache directory

.temp

# Docusaurus cache and generated files

.docusaurus

# Serverless directories

.serverless/

# FuseBox cache

.fusebox/

# DynamoDB Local files

.dynamodb/

# TernJS port file

.tern-port

# Stores VSCode versions used for testing VSCode extensions

.vscode-test

# yarn v2

.yarn/cache
.yarn/unplugged
.yarn/build-state.yml
.yarn/install-state.gz
.pnp.*

# IntelliJ based IDEs
.idea

# Finder (MacOS) folder config
.DS_Store
60 changes: 60 additions & 0 deletions examples/bible-audiobook/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
# bible-audiobook

## Why? Because I can, that's why

I grabbed a copy of the American King James Bible at [openbible.com](https://openbible.com/texts.htm)
I wrote me a script to call the mx_audio.server and convert, verse by verse.
It took me **28 hours and 05 minutes** to convert all **31,102** verses, resulting in **86h32m36s**.
I ran it on a Mac Mini M4pro, 12 cores, 24GB Ram;

![Screenshot 2025-03-18 at 14 52 35](https://github.com/user-attachments/assets/4a213b39-a24c-4e93-b0dc-04b385ea20ed)


Some example results, are located at `./audios/bible_akjv`

## Want to try it yourself?

#### just do it!

#### Notes:

- I am a javascript developer so all the code is in javascript / typescript
- I work specifically with bun, and there is code here that won't work in nodejs
- for the code to work flawlessly (fault tolerant) and as is, you need to also have a nodejs installation so you can run the mlx_audio.server running through [pm2](https://pm2.keymetrics.io/)
- you can do it without node and pm2 but there's a close to 100% chance the mlx_audio.server will crash a few times during the hard work so i built a mechanism that depends on pm2 so it doesn't need my manual intervention to keep going
- before running any of the scripts, edit the file to change your output directories and what not
- if the process does crash, or if you need to stop / pause the process, change the value on _line 37_ of `./src/index.ts` so you can pick up where it left off

### Instructions

install [Bun](https://bun.sh) if you don't have it

```bash
curl -fsSL https://bun.sh/install | bash
```

- Install local dependencies:

```bash
bun install
```

to synthesize the whole American King James Bible, run:

```bash
bun run src/index.ts
```

to convert all the .wav files to .mp3 (needs ffmpeg on your machine) run

```bash
bun run src/convert-to-mp3.ts
```

for statistics and to check the integrity of the **mp3** files (needs ffmpeg on your machine), run

```bash
bun run src/mp3-checker.ts
```

This project was created using `bun init` in bun v1.2.0. [Bun](https://bun.sh) is a fast all-in-one JavaScript runtime.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
31 changes: 31 additions & 0 deletions examples/bible-audiobook/bibles/bible-akjv.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
Genesis 1:1 In the beginning God created the heaven and the earth.
Genesis 1:2 And the earth was without form, and void; and darkness was on the face of the deep. And the Spirit of God moved on the face of the waters.
Genesis 1:3 And God said, Let there be light: and there was light.
Genesis 1:4 And God saw the light, that it was good: and God divided the light from the darkness.
Genesis 1:5 And God called the light Day, and the darkness he called Night. And the evening and the morning were the first day.
Genesis 1:6 And God said, Let there be a firmament in the middle of the waters, and let it divide the waters from the waters.
Genesis 1:7 And God made the firmament, and divided the waters which were under the firmament from the waters which were above the firmament: and it was so.
Genesis 1:8 And God called the firmament Heaven. And the evening and the morning were the second day.
Genesis 1:9 And God said, Let the waters under the heaven be gathered together to one place, and let the dry land appear: and it was so.
Genesis 1:10 And God called the dry land Earth; and the gathering together of the waters called he Seas: and God saw that it was good.
Genesis 1:11 And God said, Let the earth bring forth grass, the herb yielding seed, and the fruit tree yielding fruit after his kind, whose seed is in itself, on the earth: and it was so.
Genesis 1:12 And the earth brought forth grass, and herb yielding seed after his kind, and the tree yielding fruit, whose seed was in itself, after his kind: and God saw that it was good.
Genesis 1:13 And the evening and the morning were the third day.
Genesis 1:14 And God said, Let there be lights in the firmament of the heaven to divide the day from the night; and let them be for signs, and for seasons, and for days, and years:
Genesis 1:15 And let them be for lights in the firmament of the heaven to give light on the earth: and it was so.
Genesis 1:16 And God made two great lights; the greater light to rule the day, and the lesser light to rule the night: he made the stars also.
Genesis 1:17 And God set them in the firmament of the heaven to give light on the earth,
Genesis 1:18 And to rule over the day and over the night, and to divide the light from the darkness: and God saw that it was good.
Genesis 1:19 And the evening and the morning were the fourth day.
Genesis 1:20 And God said, Let the waters bring forth abundantly the moving creature that has life, and fowl that may fly above the earth in the open firmament of heaven.
Genesis 1:21 And God created great whales, and every living creature that moves, which the waters brought forth abundantly, after their kind, and every winged fowl after his kind: and God saw that it was good.
Genesis 1:22 And God blessed them, saying, Be fruitful, and multiply, and fill the waters in the seas, and let fowl multiply in the earth.
Genesis 1:23 And the evening and the morning were the fifth day.
Genesis 1:24 And God said, Let the earth bring forth the living creature after his kind, cattle, and creeping thing, and beast of the earth after his kind: and it was so.
Genesis 1:25 And God made the beast of the earth after his kind, and cattle after their kind, and every thing that creeps on the earth after his kind: and God saw that it was good.
Genesis 1:26 And God said, Let us make man in our image, after our likeness: and let them have dominion over the fish of the sea, and over the fowl of the air, and over the cattle, and over all the earth, and over every creeping thing that creeps on the earth.
Genesis 1:27 So God created man in his own image, in the image of God created he him; male and female created he them.
Genesis 1:28 And God blessed them, and God said to them, Be fruitful, and multiply, and replenish the earth, and subdue it: and have dominion over the fish of the sea, and over the fowl of the air, and over every living thing that moves on the earth.
Genesis 1:29 And God said, Behold, I have given you every herb bearing seed, which is on the face of all the earth, and every tree, in the which is the fruit of a tree yielding seed; to you it shall be for meat.
Genesis 1:30 And to every beast of the earth, and to every fowl of the air, and to every thing that creeps on the earth, wherein there is life, I have given every green herb for meat: and it was so.
Genesis 1:31 And God saw every thing that he had made, and, behold, it was very good. And the evening and the morning were the sixth day.
48 changes: 48 additions & 0 deletions examples/bible-audiobook/bun.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

18 changes: 18 additions & 0 deletions examples/bible-audiobook/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"name": "bible-audiobook",
"module": "src/index.ts",
"type": "module",
"dependencies": {
"@types/fluent-ffmpeg": "^2.1.27",
"D": "^1.0.0",
"fluent-ffmpeg": "^2.1.3",
"mkdirp": "^3.0.1"
},
"devDependencies": {
"@types/bun": "latest",
"@types/node": "^22.13.10"
},
"peerDependencies": {
"typescript": "^5.0.0"
}
}
43 changes: 43 additions & 0 deletions examples/bible-audiobook/src/convert-to-mp3.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import fs from 'node:fs/promises'
import path from 'node:path'
import { mkdirp } from 'mkdirp'
import ffmpeg from 'fluent-ffmpeg'

const origin = 'audios/bible-akjv/am_michael';
const destination = 'audios/bible-akjv/destination';

const regex = /(\d{8})-(.+)(-)(\d+)\:(\d+)(\.wav)/

const allFiles = (await fs.readdir(origin)).toSorted();

for (let file of allFiles) {
// console.log(file)
if (file.startsWith('.')) continue;
const filePath = path.join(origin, file);
const fileStat = await fs.stat(filePath);
if (fileStat.isFile()) {
const match = file.match(regex);
//console.log(match);
const [, index, book, , chapter, verse, extension] = match!;
const idx = parseInt(index!, 10);

// if (idx < 17850) continue;

const destinationPath = path.join(destination, book!, chapter!);
await mkdirp(destinationPath);
const newFileName = `${index}_${book}_${chapter}_${verse}.mp3`;
// console.log({ newFileName });
const newFilePath = path.join(destinationPath, newFileName);
console.log(idx, newFilePath)
await new Promise((resolve, reject) => {
ffmpeg(filePath)
.toFormat('mp3')
.on('end', resolve)
.on('error', reject)
.save(newFilePath);
});
} else {
throw new Error('Not a file');
}
await new Promise(resolve => setTimeout(resolve, 500));
}
Loading