# تبدیل FLV به MP3 / MP4 — سمت کاربر

ابزار آنلاین برای تبدیل فایل‌های `.flv` کلاس‌های ضبط‌شده ویانا (Adobe Connect) به
فرمت‌های قابل پخش **MP3** و **MP4**. کل پردازش داخل مرورگر کاربر انجام می‌شود
و هیچ فایلی به سرور ارسال نمی‌شود — همه چیز با
[ffmpeg.wasm](https://ffmpegwasm.netlify.app) کار می‌کند.

## ویژگی‌ها

- انتخاب **فولدر** (کل محتوا به‌صورت بازگشتی) یا چند فایل به‌صورت دستی
- کشیدن و رها کردن (drag & drop)
- گروه‌بندی خودکار فایل‌ها:
  - `cameraVoip_N_M.flv` → صوت کلاس → ادغام و خروجی **`class-audio.mp3`**
  - `screenshare_N_M.flv` → ویدیو کلاس → ادغام و خروجی **`class-video.mp4`**
- **Blacklist** برای استریم‌های متادیتای Adobe Connect که قابل تبدیل نیستند:
  `ftchat*`, `ftcontent*`, `ftstage*`, `indexstream`, `mainstream`, `transcriptstream`
  (به‌عنوان «ناشناخته» رد می‌شوند)
- مرتب‌سازی بر اساس دو عدد انتهایی اسم (`N` اصلی و `M` ثانویه)
- **کیفیت بالای صدا**: از `filter_complex concat` استفاده می‌شود (نه concat demuxer)
  که timestamp ها را بازسازی می‌کند و مشکل DTS غیریک‌نواخت را برطرف می‌کند.
  خروجی MP3 با کیفیت `-q:a 2` (~190kbps VBR) و نرخ نمونه ۴۴.۱kHz
- پلیر **HTML5** داخل صفحه برای هر دو خروجی
- **پخش‌کننده مستقل**: بخش جدا برای پخش هر فایل MP3/MP4/WAV/WEBM ذخیره‌شده
  (بدون نیاز به تبدیل — فقط برای پخش داخل مرورگر)
- دکمه **توقف عملیات**: کاربر می‌تواند هر زمان با `ffmpeg.terminate()` پردازش را قطع کند
- **درصد پیشرفت عددی** کنار نوار + لاگ زنده FFmpeg
- دکمه دانلود برای هر خروجی
- مدیریت خطا برای فایل‌های خراب / نامعتبر (فقط در لاگ گزارش می‌شوند، بقیه پردازش
  بدون قطع ادامه می‌یابد)
- تم **لایت/دارک** با ذخیره ترجیح در `localStorage`
- فونت Vazirmatn لوکال (بدون Google Fonts)
- استفاده از نسخه **single-threaded** ffmpeg-core (بدون نیاز به COOP/COEP)

## ساختار فایل‌ها

```
flv-converter/
├── index.php                         # صفحه اصلی
├── README.md
└── assets/
    ├── css/style.css                 # استایل (شامل تم لایت/دارک)
    ├── js/app.js                     # منطق UI + تبدیل
    ├── img/logo.svg                  # لوگوی امور دانشجویی
    ├── fonts/*.woff2                 # فونت Vazirmatn
    └── vendor/ffmpeg/                # ffmpeg.wasm لوکال
        ├── ffmpeg.js                 # UMD loader
        ├── 814.ffmpeg.js             # worker bundle
        ├── ffmpeg-core.js            # emscripten wrapper
        └── ffmpeg-core.wasm          # ~30MB — موتور FFmpeg
```

## اجرا (لوکال)

```bash
cd flv-converter
php -S 0.0.0.0:8080 -t .
# http://localhost:8080 را در مرورگر باز کنید
```

> اولین اجرا حدود ۳۰MB wasm دانلود می‌شود (فقط یک‌بار؛ مرورگر کش می‌کند).

## نحوه کار داخلی

### ۱) انتخاب فایل‌ها
دو اینپوت `<input type="file">` پنهان وجود دارد: یکی با `webkitdirectory` (فولدر)
و یکی ساده (چند فایل). رویداد `drop` هم مستقیم از `DataTransfer.files` می‌خواند.
فقط فایل‌هایی که با `.flv` تمام شوند وارد لیست می‌شوند؛ تکرار بر اساس نام+سایز
حذف می‌شود.

### ۲) گروه‌بندی
```js
function categorize(file) {
  var n = file.name.toLowerCase();
  if (n.indexOf('cameravoip') === 0 || /cameravoip_\d/.test(n)) return 'audio';
  if (n.indexOf('screenshare') === 0 || /screenshare_\d/.test(n)) return 'video';
  return 'video'; // پیش‌فرض: هر .flv دیگری را ویدیو فرض کن
}
```

### ۳) مرتب‌سازی
```js
function parseSortKey(name) {
  var m = /_(\d+)_(\d+)\.flv$/i.exec(name);
  if (m) return [+m[1], +m[2]];
  return [Infinity, name.toLowerCase()];
}
```
یعنی `cameraVoip_0_3.flv` قبل از `cameraVoip_4_27.flv` می‌آید.

### ۴) تبدیل صوت (MP3)
فایل‌های FLV صوتی به FS مجازی ffmpeg نوشته می‌شوند، سپس یک فایل لیست ساخته می‌شود:
```
file 'audio_0.flv'
file 'audio_1.flv'
...
```
و ffmpeg با `concat` demuxer اجرا می‌شود:
```
ffmpeg -f concat -safe 0 -i inputs.txt -vn -c:a libmp3lame -q:a 4 out.mp3
```

### ۵) تبدیل ویدیو (MP4)
ابتدا تلاش می‌شود بدون re-encode (stream copy) کپی شود:
```
ffmpeg -f concat -safe 0 -i inputs.txt -c copy -movflags +faststart out.mp4
```
اگر کدک‌های داخل FLV در MP4 سازگار نباشند (مثل Sorenson، Speex، Nellymoser، MP3)،
به‌طور خودکار fallback به re-encode اعمال می‌شود:
```
ffmpeg -f concat -safe 0 -i inputs.txt \
  -c:v libx264 -preset veryfast -crf 24 \
  -c:a aac -b:a 128k -movflags +faststart out.mp4
```

### ۶) هندل فایل خراب
قبل از `writeFile`، هدر فایل چک می‌شود (سه بایت اول باید `FLV` باشد). اگر نبود،
فایل به لاگ اضافه می‌شود و از لیست کنار گذاشته می‌شود، بدون قطع بقیه.

## مرورگرهای پشتیبانی‌شده

- Chrome / Edge ≥ 90 ✓
- Firefox ≥ 89 ✓
- Safari ≥ 15 (ممکن است برای فایل‌های بزرگ کند باشد)
- Opera / Brave ✓

## محدودیت‌ها

- پردازش تماماً در RAM مرورگر انجام می‌شود — فایل‌های خیلی بزرگ (> چند صد
  مگابایت در مجموع) ممکن است مرورگر را کرش کنند. در این حالت بهتر است
  کلاس را به چند پک کوچک‌تر تقسیم کنید.
- re-encode ویدیو (fallback) در wasm کند است (حدود ۲-۴ برابر کندتر از
  ffmpeg native).
- برای کارکرد، مرورگر باید از WebAssembly و Web Workers پشتیبانی کند.

## تغییر لوگو

فایل `assets/img/logo.svg` را با لوگوی دلخواه امور دانشجویی جایگزین کنید.
سایز ۸۴×۸۴ پیشنهاد می‌شود.

## کپی‌رایت

© امور دانشجویی — [@omor_shahed](https://t.me/omor_shahed)
