{"_id":"@bernierllc/content-type-audio","_rev":"7-e8af39b8c413be844a0192d5f6397a1e","name":"@bernierllc/content-type-audio","dist-tags":{"latest":"1.5.0"},"versions":{"1.0.1":{"name":"@bernierllc/content-type-audio","version":"1.0.1","keywords":["audio","content-type","media","streaming","file-upload","mp3","wav","content-management"],"author":{"name":"Bernier LLC"},"license":"SEE LICENSE IN LICENSE","_id":"@bernierllc/content-type-audio@1.0.1","maintainers":[{"name":"alikhan410","email":"mczeyo@gmail.com"},{"name":"mkbernier","email":"mkbernier@gmail.com"}],"dist":{"shasum":"2a9bca156127d6895e9dda2cfca3eb49436aabbc","tarball":"https://registry.npmjs.org/@bernierllc/content-type-audio/-/content-type-audio-1.0.1.tgz","fileCount":38,"integrity":"sha512-cr1B/3mviqd6Svee0DzuvopVyvjfnwzadRhYGpefBtT5oBfm9iF0euqFIQ0vfSYmbkAAQtdZxTd4tVgYKbNW1Q==","signatures":[{"sig":"MEUCIQDXg6AUeGWKPRoVqQeXieJyQbvYk2CvWWoreXke3sdFsAIgclNbPof81bukMVXaycy8R5aUyPGnHxn/bOndwtJ0sa8=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":272795},"main":"dist/index.js","_from":"file:bernierllc-content-type-audio-1.0.1.tgz","types":"dist/index.d.ts","scripts":{"lint":"eslint src __tests__ --ext .ts","test":"jest","build":"tsc","clean":"rm -rf dist","test:run":"jest --runInBand","test:coverage":"jest --coverage"},"_npmUser":{"name":"mkbernier","email":"mkbernier@gmail.com"},"_resolved":"/private/var/folders/r0/wspnzd1s18sfjy10ffyv2qxw0000gn/T/cc86ba4493de873dffb19419f0a3c2ca/bernierllc-content-type-audio-1.0.1.tgz","_integrity":"sha512-cr1B/3mviqd6Svee0DzuvopVyvjfnwzadRhYGpefBtT5oBfm9iF0euqFIQ0vfSYmbkAAQtdZxTd4tVgYKbNW1Q==","bernierllc":{"integration":{"logger":"planned","neverhub":"optional"}},"_npmVersion":"11.6.0","description":"Base audio content type with file upload, local storage, and streaming URL capabilities","directories":{},"_nodeVersion":"24.10.0","dependencies":{"zod":"^3.22.4","@bernierllc/content-type-registry":"^1.0.3"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^29.0.0","eslint":"^8.0.0","ts-jest":"^29.0.0","typescript":"^5.0.0","@types/jest":"^29.5.0","@types/node":"^20.0.0","@typescript-eslint/parser":"^6.0.0","@typescript-eslint/eslint-plugin":"^6.0.0"},"_npmOperationalInternal":{"tmp":"tmp/content-type-audio_1.0.1_1762141927129_0.9272343197701121","host":"s3://npm-registry-packages-npm-production"}},"1.0.2":{"name":"@bernierllc/content-type-audio","version":"1.0.2","keywords":["audio","content-type","media","streaming","file-upload","mp3","wav","content-management"],"author":{"name":"Bernier LLC"},"license":"SEE LICENSE IN LICENSE","_id":"@bernierllc/content-type-audio@1.0.2","maintainers":[{"name":"alikhan410","email":"mczeyo@gmail.com"},{"name":"mkbernier","email":"mkbernier@gmail.com"}],"dist":{"shasum":"9eec935223b917ccf0179ff95c26a08ded67b1be","tarball":"https://registry.npmjs.org/@bernierllc/content-type-audio/-/content-type-audio-1.0.2.tgz","fileCount":34,"integrity":"sha512-Vu1GnzgAHmp5JrFcUqApl7+4FSivGIDVdKGLtPRktjEvdb3PHGYPqy3/c1XzTaHTWDTDUpiAek0ZtFbuukgY+A==","signatures":[{"sig":"MEQCIGbodL9de7xxhrz90c3x+tnBHtpIyxidzjEBG6h8tWxnAiBwdEpTahZcX27JNC6n5zq9VPumw8dlDo3Xf/6JTwOvqg==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":94027},"main":"dist/index.js","_from":"file:bernierllc-content-type-audio-1.0.2.tgz","types":"dist/index.d.ts","scripts":{"lint":"eslint src __tests__ --ext .ts","test":"jest","build":"tsc","clean":"rm -rf dist","test:run":"jest --runInBand","test:coverage":"jest --coverage"},"_npmUser":{"name":"mkbernier","email":"mkbernier@gmail.com"},"_resolved":"/tmp/fc7c896829b03963f71281cba493f95f/bernierllc-content-type-audio-1.0.2.tgz","_integrity":"sha512-Vu1GnzgAHmp5JrFcUqApl7+4FSivGIDVdKGLtPRktjEvdb3PHGYPqy3/c1XzTaHTWDTDUpiAek0ZtFbuukgY+A==","bernierllc":{"integration":{"logger":"planned","neverhub":"optional"}},"_npmVersion":"11.7.0","description":"Base audio content type with file upload, local storage, and streaming URL capabilities","directories":{},"_nodeVersion":"20.19.6","dependencies":{"zod":"^3.22.4","@bernierllc/content-type-registry":"1.1.0"},"publishConfig":{"access":"public","registry":"https://registry.npmjs.org/"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^29.0.0","eslint":"^8.0.0","ts-jest":"^29.0.0","typescript":"^5.0.0","@types/jest":"^29.5.0","@types/node":"^20.0.0","@typescript-eslint/parser":"^6.0.0","@typescript-eslint/eslint-plugin":"^6.0.0"},"_npmOperationalInternal":{"tmp":"tmp/content-type-audio_1.0.2_1766087433513_0.4085307778656242","host":"s3://npm-registry-packages-npm-production"}},"1.2.0":{"name":"@bernierllc/content-type-audio","version":"1.2.0","keywords":["audio","content-type","media","streaming","file-upload","mp3","wav","content-management"],"author":{"name":"Bernier LLC"},"license":"SEE LICENSE IN LICENSE","_id":"@bernierllc/content-type-audio@1.2.0","maintainers":[{"name":"alikhan410","email":"mczeyo@gmail.com"},{"name":"mkbernier","email":"mkbernier@gmail.com"}],"dist":{"shasum":"5b10a2c9743dca336534dc586fc94240ecf6936c","tarball":"https://registry.npmjs.org/@bernierllc/content-type-audio/-/content-type-audio-1.2.0.tgz","fileCount":34,"integrity":"sha512-EHQrPeD4L8XgIPvy7Tmm3yJ/ua8nIM9aTNOX0fB9K8yIWWKdCllaLV9+sA1se4R+jdqRv9OhnMXvTU1MRRh9xQ==","signatures":[{"sig":"MEUCIDHFuUbSU+WZFOVSNGoZM2kF2q29HG6ptFkDrxTrIIF0AiEArSSx6DgBNZp3I5ScA/0Dmn7pSh5gDtA740hRVlAC+iM=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":96773},"main":"dist/index.js","types":"dist/index.d.ts","gitHead":"af7e74b3715d56d3a193e1bb6743b337c2b0df6d","scripts":{"lint":"eslint src __tests__ --ext .ts","test":"jest","build":"tsc","clean":"rm -rf dist","test:run":"jest --runInBand","test:coverage":"jest --coverage"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:cbf04df7-eea6-4fe4-91fb-83ca9a29263a"}},"bernierllc":{"integration":{"logger":"planned","neverhub":"optional"}},"_npmVersion":"lerna/9.0.3/node@v20.19.6+x64 (linux)","description":"Base audio content type with file upload, local storage, and streaming URL capabilities","directories":{},"_nodeVersion":"20.19.6","dependencies":{"zod":"^3.22.4","@bernierllc/content-type-registry":"1.3.0"},"publishConfig":{"access":"public","registry":"https://registry.npmjs.org/"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^29.0.0","eslint":"^8.0.0","ts-jest":"^29.0.0","typescript":"^5.0.0","@types/jest":"^29.5.0","@types/node":"^20.0.0","@typescript-eslint/parser":"^6.0.0","@typescript-eslint/eslint-plugin":"^6.0.0"},"_npmOperationalInternal":{"tmp":"tmp/content-type-audio_1.2.0_1767642378851_0.8923068312788189","host":"s3://npm-registry-packages-npm-production"}},"1.2.1":{"name":"@bernierllc/content-type-audio","version":"1.2.1","keywords":["audio","content-type","media","streaming","file-upload","mp3","wav","content-management"],"author":{"name":"Bernier LLC"},"license":"SEE LICENSE IN LICENSE","_id":"@bernierllc/content-type-audio@1.2.1","maintainers":[{"name":"alikhan410","email":"mczeyo@gmail.com"},{"name":"mkbernier","email":"mkbernier@gmail.com"}],"dist":{"shasum":"df9b07639407dd46c91cb3580ac0f4a3c4d26abc","tarball":"https://registry.npmjs.org/@bernierllc/content-type-audio/-/content-type-audio-1.2.1.tgz","fileCount":34,"integrity":"sha512-GXJ/i52fLibbxlr9GLLQm8Tq6iWWn8RtX2rkw/Xfj78rQnU0+RmP0itfnnQpHTlJRdLE2h5rarhpVLYlvKjFXQ==","signatures":[{"sig":"MEUCIQDuXvA+Wq2yAqe/vUTVIxwf/9x1sSbjl85CwqvgZ6ODIAIgMzE+tOsih7rUPuIKxWdOsbACCIwaQopDbIyB4isEJuQ=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":96937},"main":"dist/index.js","_from":"file:bernierllc-content-type-audio-1.2.1.tgz","types":"dist/index.d.ts","scripts":{"lint":"eslint src __tests__ --ext .ts","test":"jest","build":"tsc","clean":"rm -rf dist","test:run":"jest --runInBand","test:coverage":"jest --coverage"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:cbf04df7-eea6-4fe4-91fb-83ca9a29263a"}},"_resolved":"/tmp/de4b4f363f5d185adc1217b92450629b/bernierllc-content-type-audio-1.2.1.tgz","_integrity":"sha512-GXJ/i52fLibbxlr9GLLQm8Tq6iWWn8RtX2rkw/Xfj78rQnU0+RmP0itfnnQpHTlJRdLE2h5rarhpVLYlvKjFXQ==","bernierllc":{"integration":{"logger":"planned","neverhub":"optional"}},"_npmVersion":"11.11.0","description":"Base audio content type with file upload, local storage, and streaming URL capabilities","directories":{},"_nodeVersion":"20.20.0","dependencies":{"zod":"^3.22.4","@bernierllc/content-type-registry":"1.3.1"},"publishConfig":{"access":"public","registry":"https://registry.npmjs.org/"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^29.0.0","eslint":"^8.0.0","ts-jest":"^29.0.0","typescript":"^5.0.0","@types/jest":"^29.5.0","@types/node":"^20.0.0","@typescript-eslint/parser":"^6.0.0","@typescript-eslint/eslint-plugin":"^6.0.0"},"_npmOperationalInternal":{"tmp":"tmp/content-type-audio_1.2.1_1773078374291_0.13323561370074466","host":"s3://npm-registry-packages-npm-production"}},"1.2.2":{"name":"@bernierllc/content-type-audio","version":"1.2.2","keywords":["audio","content-type","media","streaming","file-upload","mp3","wav","content-management"],"author":{"name":"Bernier LLC"},"license":"SEE LICENSE IN LICENSE","_id":"@bernierllc/content-type-audio@1.2.2","maintainers":[{"name":"alikhan410","email":"mczeyo@gmail.com"},{"name":"mkbernier","email":"mkbernier@gmail.com"}],"dist":{"shasum":"6be47ee9ab06dcbb172ef5812edf0981e0fb62c9","tarball":"https://registry.npmjs.org/@bernierllc/content-type-audio/-/content-type-audio-1.2.2.tgz","fileCount":34,"integrity":"sha512-X5q+kGUty3+ymWbJpwPTjN/qJQiWmg7LLNWY5b7yN9sKnBsKy5uDDRcWR6wViBM84TONxjbv8XXBKvtLm/rEPA==","signatures":[{"sig":"MEUCIHnG6RFXhM+WQFCJT32T/OmWQsVuKdsWENiBGNjKwjIJAiEA1migHFIILbLdzCtm510eGNo8eeG8KNUcCqw+0e8v+1Q=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":97159},"main":"dist/index.js","_from":"file:bernierllc-content-type-audio-1.2.2.tgz","types":"dist/index.d.ts","scripts":{"lint":"eslint src __tests__ --ext .ts","test":"jest","build":"tsc","clean":"rm -rf dist","test:run":"jest --runInBand","test:coverage":"jest --coverage"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:cbf04df7-eea6-4fe4-91fb-83ca9a29263a"}},"_resolved":"/home/runner/work/tools/tools/packages/core/content-type-audio/bernierllc-content-type-audio-1.2.2.tgz","_integrity":"sha512-X5q+kGUty3+ymWbJpwPTjN/qJQiWmg7LLNWY5b7yN9sKnBsKy5uDDRcWR6wViBM84TONxjbv8XXBKvtLm/rEPA==","bernierllc":{"integration":{"logger":"planned","neverhub":"optional"}},"_npmVersion":"11.11.0","description":"Base audio content type with file upload, local storage, and streaming URL capabilities","directories":{},"_nodeVersion":"20.20.0","dependencies":{"zod":"^3.22.4","@bernierllc/content-type-registry":"1.3.2"},"publishConfig":{"access":"public","registry":"https://registry.npmjs.org/"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^29.0.0","eslint":"^8.0.0","ts-jest":"^29.0.0","typescript":"^5.0.0","@types/jest":"^29.5.0","@types/node":"^20.0.0","@typescript-eslint/parser":"^6.0.0","@typescript-eslint/eslint-plugin":"^6.0.0"},"_npmOperationalInternal":{"tmp":"tmp/content-type-audio_1.2.2_1773163064868_0.8789875998908678","host":"s3://npm-registry-packages-npm-production"}},"1.4.0":{"name":"@bernierllc/content-type-audio","version":"1.4.0","keywords":["audio","content-type","media","streaming","file-upload","mp3","wav","content-management"],"author":{"name":"Bernier LLC"},"license":"SEE LICENSE IN LICENSE","_id":"@bernierllc/content-type-audio@1.4.0","maintainers":[{"name":"alikhan410","email":"mczeyo@gmail.com"},{"name":"mkbernier","email":"mkbernier@gmail.com"}],"dist":{"shasum":"f4e9187ee4dc60e7f2862a70502b89c089fa8f3a","tarball":"https://registry.npmjs.org/@bernierllc/content-type-audio/-/content-type-audio-1.4.0.tgz","fileCount":26,"integrity":"sha512-Qg7OnjaQkYRyf04yYWqSr7CVoWBh0X/j+M5G1FdVLPk61Q6mTS6ha8gDEcGztjfOQ/MVzXAwvVYQTiZJeAnhcQ==","signatures":[{"sig":"MEQCIBcc0Wj/MkVeESFx8PCD3QhZXBpjrdFBx9QquiCglDHTAiAZq6iiPU36w4GdsVDvLh2hrJsrGy1xW5aK9X79TDQswA==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":51355},"main":"dist/index.js","_from":"file:bernierllc-content-type-audio-1.4.0.tgz","types":"dist/index.d.ts","scripts":{"lint":"eslint src __tests__ --ext .ts","test":"jest","build":"tsc","clean":"rm -rf dist","test:run":"jest --runInBand","test:coverage":"jest --coverage"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:cbf04df7-eea6-4fe4-91fb-83ca9a29263a"}},"_resolved":"/home/runner/work/tools/tools/packages/core/content-type-audio/bernierllc-content-type-audio-1.4.0.tgz","_integrity":"sha512-Qg7OnjaQkYRyf04yYWqSr7CVoWBh0X/j+M5G1FdVLPk61Q6mTS6ha8gDEcGztjfOQ/MVzXAwvVYQTiZJeAnhcQ==","bernierllc":{"integration":{"logger":"planned","neverhub":"optional"}},"_npmVersion":"11.14.1","description":"Base audio content type with file upload, local storage, and streaming URL capabilities","directories":{},"_nodeVersion":"20.20.2","dependencies":{"zod":"^3.22.4","@bernierllc/content-type-registry":"1.5.0"},"publishConfig":{"access":"public","registry":"https://registry.npmjs.org/"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^29.0.0","eslint":"^8.0.0","ts-jest":"^29.0.0","typescript":"^5.0.0","@types/jest":"^29.5.0","@types/node":"^20.0.0","@typescript-eslint/parser":"^6.0.0","@typescript-eslint/eslint-plugin":"^6.0.0"},"_npmOperationalInternal":{"tmp":"tmp/content-type-audio_1.4.0_1779240998666_0.14869091311039173","host":"s3://npm-registry-packages-npm-production"}},"1.5.0":{"name":"@bernierllc/content-type-audio","version":"1.5.0","description":"Base audio content type with file upload, local storage, and streaming URL capabilities","main":"dist/index.js","types":"dist/index.d.ts","keywords":["audio","content-type","media","streaming","file-upload","mp3","wav","content-management"],"author":{"name":"Bernier LLC"},"license":"SEE LICENSE IN LICENSE","dependencies":{"zod":"^3.22.4","@bernierllc/content-type-registry":"1.6.0"},"devDependencies":{"@types/jest":"^29.5.0","@types/node":"^20.0.0","@typescript-eslint/eslint-plugin":"^6.0.0","@typescript-eslint/parser":"^6.0.0","eslint":"^8.0.0","jest":"^29.0.0","ts-jest":"^29.0.0","typescript":"^5.0.0"},"publishConfig":{"access":"public","registry":"https://registry.npmjs.org/"},"bernierllc":{"integration":{"neverhub":"optional","logger":"planned"}},"scripts":{"build":"tsc","test":"jest","test:run":"jest --runInBand","test:coverage":"jest --coverage","lint":"eslint src __tests__ --ext .ts","clean":"rm -rf dist"},"_id":"@bernierllc/content-type-audio@1.5.0","_integrity":"sha512-K3RlcMRU6uWx8UkqkRbEbdXlJh59zW6epSQHzf92VC/SMtyjyY9K1UcGE5wfCItWqKgcgCNo4NUcCT7hj/2dFg==","_resolved":"/home/runner/work/tools/tools/packages/core/content-type-audio/bernierllc-content-type-audio-1.5.0.tgz","_from":"file:bernierllc-content-type-audio-1.5.0.tgz","_nodeVersion":"20.20.2","_npmVersion":"11.14.1","dist":{"integrity":"sha512-K3RlcMRU6uWx8UkqkRbEbdXlJh59zW6epSQHzf92VC/SMtyjyY9K1UcGE5wfCItWqKgcgCNo4NUcCT7hj/2dFg==","shasum":"c149c33997f3508dbc2017d9c577df62c3800feb","tarball":"https://registry.npmjs.org/@bernierllc/content-type-audio/-/content-type-audio-1.5.0.tgz","fileCount":26,"unpackedSize":51355,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQD42x+yk/9KmLDTLMrfVbS1DkGB5QE3LodsmhV91+ZSXAIhAJ2PNNk82LotmAg5oStJ/Cly16OrhnfNzaz56aJYXKyc"}]},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:cbf04df7-eea6-4fe4-91fb-83ca9a29263a"}},"directories":{},"maintainers":[{"name":"alikhan410","email":"mczeyo@gmail.com"},{"name":"mkbernier","email":"mkbernier@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/content-type-audio_1.5.0_1779249735190_0.5276144764310087"},"_hasShrinkwrap":false}},"time":{"created":"2025-11-03T03:52:07.013Z","modified":"2026-05-20T04:02:15.441Z","1.0.1":"2025-11-03T03:52:07.313Z","1.0.2":"2025-12-18T19:50:33.662Z","1.2.0":"2026-01-05T19:46:19.004Z","1.2.1":"2026-03-09T17:46:14.435Z","1.2.2":"2026-03-10T17:17:45.020Z","1.4.0":"2026-05-20T01:36:38.815Z","1.5.0":"2026-05-20T04:02:15.315Z"},"author":{"name":"Bernier LLC"},"license":"SEE LICENSE IN LICENSE","keywords":["audio","content-type","media","streaming","file-upload","mp3","wav","content-management"],"description":"Base audio content type with file upload, local storage, and streaming URL capabilities","maintainers":[{"name":"alikhan410","email":"mczeyo@gmail.com"},{"name":"mkbernier","email":"mkbernier@gmail.com"}],"readme":"# @bernierllc/content-type-audio\n\nBase audio content type with file upload, local storage, and streaming URL capabilities. Provides comprehensive audio content management for podcasts, voice notes, and music files.\n\n## Installation\n\n```bash\nnpm install @bernierllc/content-type-audio\n```\n\n## Features\n\n- **Audio File Validation** - MIME type, size, and duration validation\n- **File Upload Handling** - Audio preview and metadata extraction\n- **Local File System Storage** - Organized file storage with path management\n- **URL Publishing** - Streaming URLs for stored audio files\n- **Metadata Management** - Duration, bitrate, sample rate, codec information\n- **Multiple Format Support** - MP3, WAV, AAC, OGG, FLAC, M4A\n- **Utility Functions** - Duration parsing/formatting, bitrate calculation\n- **Extensible Architecture** - Base for specialized audio content types\n\n## Usage\n\n### Basic Setup\n\n```typescript\nimport { AudioContentTypeManager, AudioFormat } from '@bernierllc/content-type-audio';\nimport { ContentTypeRegistry } from '@bernierllc/content-type-registry';\n\n// Create manager with default configuration\nconst manager = new AudioContentTypeManager();\n\n// Register with content type registry\nconst registry = new ContentTypeRegistry();\nmanager.register(registry);\n```\n\n### Creating Audio Content\n\n```typescript\n// Create audio content with required metadata\nconst audioContent = manager.create({\n  filename: 'podcast-episode-01.mp3',\n  mimeType: AudioFormat.MP3,\n  size: 5242880, // 5MB\n  duration: 1800, // 30 minutes\n  bitrate: 192,\n  title: 'Introduction to TypeScript',\n  artist: 'Tech Talks Podcast'\n});\n\nconsole.log(audioContent);\n// {\n//   id: 'audio_1234567890_abc123',\n//   type: 'audio',\n//   metadata: {\n//     filename: 'podcast-episode-01.mp3',\n//     mimeType: 'audio/mpeg',\n//     size: 5242880,\n//     duration: 1800,\n//     bitrate: 192,\n//     title: 'Introduction to TypeScript',\n//     artist: 'Tech Talks Podcast'\n//   },\n//   createdAt: Date,\n//   updatedAt: Date\n// }\n```\n\n### Creating Audio with Storage and URLs\n\n```typescript\n// Create audio content with file path and streaming URL\nconst audioWithStorage = manager.create(\n  {\n    filename: 'voice-note.m4a',\n    mimeType: AudioFormat.M4A,\n    size: 1048576, // 1MB\n    duration: 120, // 2 minutes\n    bitrate: 64\n  },\n  {\n    filePath: '/storage/audio/voice-note-20250102.m4a',\n    fileUrl: 'file:///storage/audio/voice-note-20250102.m4a',\n    streamingUrl: 'https://cdn.example.com/audio/voice-note-20250102.m4a'\n  }\n);\n\nconsole.log(audioWithStorage.filePath);\n// '/storage/audio/voice-note-20250102.m4a'\n\nconsole.log(audioWithStorage.streamingUrl);\n// 'https://cdn.example.com/audio/voice-note-20250102.m4a'\n```\n\n### Validating Audio Content\n\n```typescript\n// Validate audio content\nconst validation = manager.validate(audioContent);\n\nif (validation.valid) {\n  console.log('Audio content is valid');\n  console.log('Metadata:', validation.metadata);\n} else {\n  console.error('Validation errors:', validation.errors);\n}\n\n// Example validation with errors\nconst invalidContent = manager.create({\n  filename: 'large-file.wav',\n  mimeType: AudioFormat.WAV,\n  size: 200 * 1024 * 1024, // 200MB (exceeds default 100MB limit)\n  duration: 3600,\n  bitrate: 1411\n});\n\nconst result = manager.validate(invalidContent);\nconsole.log(result.valid); // false\nconsole.log(result.errors); // ['File size exceeds maximum allowed size']\n```\n\n### Custom Configuration\n\n```typescript\n// Create manager with custom configuration\nconst customManager = new AudioContentTypeManager({\n  maxFileSize: 50 * 1024 * 1024, // 50MB limit\n  allowedFormats: [AudioFormat.MP3, AudioFormat.AAC], // Only MP3 and AAC\n  requireMetadata: true // Require title/artist metadata\n});\n\n// This will fail validation (exceeds size limit)\nconst largeAudio = customManager.create({\n  filename: 'large-podcast.mp3',\n  mimeType: AudioFormat.MP3,\n  size: 75 * 1024 * 1024, // 75MB\n  duration: 4500,\n  bitrate: 128\n});\n\nconst validation = customManager.validate(largeAudio);\nconsole.log(validation.valid); // false\nconsole.log(validation.errors); // ['File size exceeds maximum allowed size']\n```\n\n### Duration Utilities\n\n```typescript\n// Parse duration from various formats\nconst seconds1 = manager.parseDuration(90); // 90\nconst seconds2 = manager.parseDuration('1:30'); // 90 (1 minute 30 seconds)\nconst seconds3 = manager.parseDuration('1:23:45'); // 5025 (1 hour 23 minutes 45 seconds)\n\n// Format duration to human-readable string\nconst formatted1 = manager.formatDuration(90); // '1:30'\nconst formatted2 = manager.formatDuration(5025); // '1:23:45'\nconst formatted3 = manager.formatDuration(3600); // '1:00:00'\n```\n\n### Bitrate Calculation\n\n```typescript\n// Calculate bitrate from file size and duration\nconst fileSize = 5 * 1024 * 1024; // 5MB\nconst duration = 180; // 3 minutes\n\nconst bitrate = manager.calculateBitrate(fileSize, duration);\nconsole.log(bitrate); // ~233 kbps\n\n// Example with different scenarios\nconst mp3Size = Math.round((128 * 1000 * 180) / 8); // 128kbps MP3, 3 minutes\nconst mp3Bitrate = manager.calculateBitrate(mp3Size, 180);\nconsole.log(mp3Bitrate); // 128 kbps\n\nconst wavSize = Math.round((1411 * 1000 * 300) / 8); // CD quality WAV, 5 minutes\nconst wavBitrate = manager.calculateBitrate(wavSize, 300);\nconsole.log(wavBitrate); // 1411 kbps\n```\n\n## Integration with ContentTypeRegistry\n\n```typescript\nimport { ContentTypeRegistry } from '@bernierllc/content-type-registry';\nimport { AudioContentTypeManager } from '@bernierllc/content-type-audio';\n\n// Create registry and manager\nconst registry = new ContentTypeRegistry();\nconst audioManager = new AudioContentTypeManager();\n\n// Register audio content type\naudioManager.register(registry);\n\n// Retrieve audio content type from registry\nconst result = registry.get('audio');\nif (result.success && result.data) {\n  console.log('Content Type ID:', result.data.id); // 'audio'\n  console.log('Content Type Name:', result.data.name); // 'Audio'\n  console.log('Base Type:', result.data.baseType); // 'audio'\n}\n\n// List audio content types\nconst audioTypes = registry.list({ baseType: 'audio' });\nif (audioTypes.success && audioTypes.data) {\n  console.log('Audio types:', audioTypes.data.length); // 1\n  console.log('First type:', audioTypes.data[0].name); // 'Audio'\n}\n\n// Use registry to validate content\nconst content = audioManager.create({\n  filename: 'test.mp3',\n  mimeType: AudioFormat.MP3,\n  size: 1024 * 1024,\n  duration: 60,\n  bitrate: 128\n});\n\nconst validation = audioManager.validate(content);\nconsole.log('Is valid:', validation.valid); // true\n```\n\n## API Reference\n\n### AudioContentTypeManager\n\n#### Constructor\n\n```typescript\nconstructor(config?: Partial<AudioContentTypeConfig>)\n```\n\nCreates a new AudioContentTypeManager with optional configuration.\n\n**Configuration Options:**\n- `baseType: string` - Base content type (default: 'audio')\n- `editor: string` - Editor type (default: 'file-upload-with-player')\n- `storage: string` - Storage type (default: 'file')\n- `publishing: string` - Publishing type (default: 'streaming-url')\n- `maxFileSize: number` - Maximum file size in bytes (default: 100MB)\n- `allowedFormats: AudioFormat[]` - Allowed audio formats (default: all formats)\n- `requireMetadata: boolean` - Require title/artist metadata (default: false)\n\n#### Methods\n\n##### register(registry: ContentTypeRegistry): void\n\nRegisters the audio content type with a ContentTypeRegistry.\n\n##### create(metadata: AudioMetadata, options?: Partial<AudioContentType>): AudioContentType\n\nCreates a new audio content instance with the provided metadata.\n\n**Parameters:**\n- `metadata: AudioMetadata` - Required audio metadata (filename, mimeType, size, duration, bitrate)\n- `options?: Partial<AudioContentType>` - Optional fields (filePath, fileUrl, streamingUrl)\n\n**Returns:** Complete AudioContentType object with generated ID and timestamps.\n\n##### validate(content: unknown): AudioValidationResult\n\nValidates audio content against configuration rules.\n\n**Returns:**\n```typescript\n{\n  valid: boolean;\n  metadata: AudioMetadata;\n  errors?: string[]; // Only present if valid is false\n}\n```\n\n##### parseDuration(duration: string | number): number\n\nParses duration from various formats to seconds.\n\n**Supported Formats:**\n- Number: `90` → 90 seconds\n- Seconds string: `\"90\"` → 90 seconds\n- mm:ss format: `\"1:30\"` → 90 seconds\n- hh:mm:ss format: `\"1:23:45\"` → 5025 seconds\n\n##### formatDuration(seconds: number): string\n\nFormats duration in seconds to human-readable string.\n\n**Returns:**\n- Under 1 hour: `\"mm:ss\"` (e.g., \"23:45\")\n- Over 1 hour: `\"hh:mm:ss\"` (e.g., \"1:23:45\")\n\n##### calculateBitrate(fileSize: number, duration: number): number\n\nCalculates bitrate in kbps from file size and duration.\n\n**Parameters:**\n- `fileSize: number` - File size in bytes\n- `duration: number` - Duration in seconds\n\n**Returns:** Bitrate in kbps (rounded to nearest integer)\n\n### Types\n\n#### AudioFormat\n\n```typescript\nenum AudioFormat {\n  MP3 = 'audio/mpeg',\n  WAV = 'audio/wav',\n  AAC = 'audio/aac',\n  OGG = 'audio/ogg',\n  FLAC = 'audio/flac',\n  M4A = 'audio/mp4'\n}\n```\n\n#### AudioMetadata\n\n```typescript\ninterface AudioMetadata {\n  filename: string;\n  mimeType: AudioFormat;\n  size: number; // bytes\n  duration: number; // seconds\n  bitrate: number; // kbps\n  sampleRate?: number; // Hz\n  channels?: number; // 1 (mono), 2 (stereo), etc.\n  title?: string;\n  artist?: string;\n  album?: string;\n  year?: number;\n  coverArt?: string; // URL or base64\n}\n```\n\n#### AudioContentType\n\n```typescript\ninterface AudioContentType {\n  id: string;\n  type: 'audio';\n  metadata: AudioMetadata;\n  filePath?: string;\n  fileUrl?: string;\n  streamingUrl?: string;\n  createdAt: Date;\n  updatedAt: Date;\n}\n```\n\n#### AudioValidationResult\n\n```typescript\ninterface AudioValidationResult {\n  valid: boolean;\n  metadata: AudioMetadata;\n  errors?: string[]; // Only present when valid is false\n}\n```\n\n## Configuration\n\n### Environment Variables\n\nNone required. All configuration is passed via constructor options.\n\n### Default Configuration\n\n```typescript\n{\n  baseType: 'audio',\n  editor: 'file-upload-with-player',\n  storage: 'file',\n  publishing: 'streaming-url',\n  maxFileSize: 100 * 1024 * 1024, // 100MB\n  allowedFormats: [\n    AudioFormat.MP3,\n    AudioFormat.WAV,\n    AudioFormat.AAC,\n    AudioFormat.OGG,\n    AudioFormat.FLAC,\n    AudioFormat.M4A\n  ],\n  requireMetadata: false\n}\n```\n\n## Examples\n\n### Podcast Episode Management\n\n```typescript\nconst podcastManager = new AudioContentTypeManager({\n  maxFileSize: 200 * 1024 * 1024, // 200MB for long episodes\n  allowedFormats: [AudioFormat.MP3, AudioFormat.M4A],\n  requireMetadata: true\n});\n\nconst episode = podcastManager.create(\n  {\n    filename: 'ep001-introduction.mp3',\n    mimeType: AudioFormat.MP3,\n    size: 50 * 1024 * 1024,\n    duration: 3600, // 1 hour\n    bitrate: 128,\n    title: 'Episode 1: Introduction',\n    artist: 'My Podcast',\n    album: 'Season 1',\n    year: 2025\n  },\n  {\n    filePath: '/podcasts/season1/ep001.mp3',\n    streamingUrl: 'https://cdn.mypodcast.com/season1/ep001.mp3'\n  }\n);\n\nconst validation = podcastManager.validate(episode);\nif (validation.valid) {\n  console.log('Episode ready for publishing');\n  console.log('Duration:', podcastManager.formatDuration(episode.metadata.duration));\n  console.log('Streaming URL:', episode.streamingUrl);\n}\n```\n\n### Voice Note Recording\n\n```typescript\nconst voiceNoteManager = new AudioContentTypeManager({\n  maxFileSize: 10 * 1024 * 1024, // 10MB for voice notes\n  allowedFormats: [AudioFormat.M4A, AudioFormat.AAC],\n  requireMetadata: false\n});\n\nconst voiceNote = voiceNoteManager.create({\n  filename: 'voice-note-20250102.m4a',\n  mimeType: AudioFormat.M4A,\n  size: 512 * 1024, // 512KB\n  duration: 60, // 1 minute\n  bitrate: 64,\n  sampleRate: 44100,\n  channels: 1\n});\n\nconsole.log('Voice note created:', voiceNote.id);\nconsole.log('Duration:', voiceNoteManager.formatDuration(voiceNote.metadata.duration));\n```\n\n### Music Library\n\n```typescript\nconst musicManager = new AudioContentTypeManager({\n  maxFileSize: 50 * 1024 * 1024, // 50MB for high-quality audio\n  allowedFormats: [AudioFormat.FLAC, AudioFormat.MP3],\n  requireMetadata: true\n});\n\nconst song = musicManager.create(\n  {\n    filename: 'track01.flac',\n    mimeType: AudioFormat.FLAC,\n    size: 30 * 1024 * 1024,\n    duration: 240, // 4 minutes\n    bitrate: 1411, // CD quality\n    sampleRate: 44100,\n    channels: 2,\n    title: 'Amazing Song',\n    artist: 'Great Artist',\n    album: 'Awesome Album',\n    year: 2025,\n    coverArt: 'https://cdn.music.com/covers/album123.jpg'\n  },\n  {\n    filePath: '/music/library/track01.flac',\n    streamingUrl: 'https://stream.music.com/track01'\n  }\n);\n\nconst validation = musicManager.validate(song);\nconsole.log('Song validated:', validation.valid);\nconsole.log('Title:', validation.metadata.title);\nconsole.log('Artist:', validation.metadata.artist);\n```\n\n## Integration Status\n\n- **Logger**: not-applicable - Core package with no logging requirements\n- **Docs-Suite**: ready - Complete JSDoc documentation and markdown README\n- **NeverHub**: not-applicable - Core utility package with no event requirements\n\n## See Also\n\n- [@bernierllc/content-type-registry](https://www.npmjs.com/package/@bernierllc/content-type-registry) - Content type registration and management\n- [@bernierllc/content-type-video](https://www.npmjs.com/package/@bernierllc/content-type-video) - Video content type management\n- [@bernierllc/content-type-image](https://www.npmjs.com/package/@bernierllc/content-type-image) - Image content type management\n\n## License\n\nCopyright (c) 2025 Bernier LLC\n\nThis file is licensed to the client under a limited-use license.\nThe client may use and modify this code *only within the scope of the project it was delivered for*.\nRedistribution or use in other products or commercial offerings is not permitted without written consent from Bernier LLC.\n","readmeFilename":"README.md"}