diff --git a/.htaccess b/.htaccess
index 41521d2..e75f798 100644
--- a/.htaccess
+++ b/.htaccess
@@ -20,6 +20,15 @@
+# Voice playback MIME types, including Safari/iPhone-compatible AAC in MP4.
+
+ AddType audio/webm .webm
+ AddType audio/wav .wav
+ AddType audio/aac .aac
+ AddType audio/mp4 .m4a
+ AddType video/mp4 .mp4
+
+
# Deny direct access to storage and internal PHP libraries
RewriteEngine On
diff --git a/README.md b/README.md
index dd6c208..dbe1224 100644
--- a/README.md
+++ b/README.md
@@ -13,6 +13,7 @@ CyberChat is a framework-free PHP, SQLite, JavaScript, and HTML5 chat applicatio
- Premium-configurable recording presence for both sending and viewing
- Premium-configurable automatic voice sending
- Tier-configurable automatic playback of newly received voice clips
+- Optional FFmpeg voice transcoding to iPhone-compatible AAC/M4A or H.264/AAC MP4
- Administrator tier overrides that grant plan features without payment
- Single-worker queued polling with cursor catch-up, request timeouts, deduplication, bounded retry backoff, and a capped browser message buffer
- Plan-based custom username colors
@@ -29,6 +30,7 @@ CyberChat is a framework-free PHP, SQLite, JavaScript, and HTML5 chat applicatio
- A web server with HTTPS for production
- Write access to `db/`, `archive/`, `uploads/voice/`, and `config.json`
- A modern browser with `MediaRecorder` for voice recording
+- Optional: FFmpeg with AAC support; `libx264` is also required for the H.264 profile
- Optional: PDO MySQL for the MySQL/MariaDB mirror
## Installation
@@ -38,7 +40,7 @@ CyberChat is a framework-free PHP, SQLite, JavaScript, and HTML5 chat applicatio
3. Configure Apache with the included `.htaccess`, or adapt `nginx-example.conf`.
4. Open `admin.php` and sign in with the initial password `changeme123`.
5. Immediately change `admin.password` in the Configuration tab.
-6. Open **Plans & Platform** to configure tiers, Mailgun, Stripe, and optional MySQL mirroring.
+6. Open **Plans & Platform** to configure tiers, Mailgun, Stripe, optional voice transcoding, and MySQL mirroring.
The SQLite schema and default Free, Plus, and Pro tiers are created automatically on first use.
@@ -115,6 +117,21 @@ Stripe references:
-
-
+## Voice Compatibility and FFmpeg
+
+Browsers that support WebM continue to record WebM by default. Safari and iPhone may record MP4/AAC instead, which the upload API also accepts.
+
+Under **Admin > Plans & Platform > Voice Transcoding / FFmpeg**, configure:
+
+- Enable or disable server-side transcoding
+- FFmpeg executable name or absolute path
+- `M4A / AAC-LC`, recommended for audio-only playback on iPhone, Safari, Android, and desktop
+- `MP4 / H.264 + AAC`, which adds a tiny black H.264 video track for systems requiring a conventional MP4
+- Audio bitrate and conversion timeout
+- Whether to retain the original source when conversion fails
+
+When transcoding is disabled, the original browser recording is stored. WebM remains the preferred default on supported browsers. When enabled, new uploads are converted; existing voice files are unchanged.
+
## Archives
The application archives daily messages into:
@@ -143,7 +160,7 @@ Set a PDO MySQL DSN in the dashboard, enable the mirror, and optionally enable a
-
+
@@ -166,6 +183,7 @@ api/stripe-webhook.php Stripe event synchronization
assets/js/cyberchat-app.js Browser application
lib/mailer.php Reusable Mailgun sender
lib/stripe.php Stripe REST client and subscription sync
+lib/voice_transcoder.php Optional FFmpeg voice compatibility pipeline
lib/mysql_mirror.php Optional SQLite-to-MySQL mirror
```
diff --git a/admin.php b/admin.php
index 8405866..450db21 100644
--- a/admin.php
+++ b/admin.php
@@ -1729,6 +1729,12 @@ td.actions{white-space:nowrap;width:1px}
voice.max_duration_seconds
integer
Maximum voice clip duration
voice.max_upload_bytes
integer
Maximum recording upload size
voice.auto_play_default
bool
Queue and play incoming clips sequentially by default