# BÁO CÁO KHẢO SÁT CHUYÊN SÂU KỸ THUẬT: PIPELINE, 4-STEM AUDIO & WEB REVIEW STUDIO (PORT 1515)
## DỰ ÁN ĐIỆN ẢNH AI: THẬP NGŨ NIÊN (THE FIFTEEN SPRINGS)

- **Người thực hiện**: `teamwork_preview_explorer` (Pipeline, Audio & Review Studio Explorer)
- **Thời gian hoàn thành**: 2026-10-08T04:16:00Z
- **Phạm vi khảo sát**: Yêu cầu R6 (4-Stem Audio & Ambience Continuity) và R7 (Production Automation & Web Review Studio Port 1515) phục vụ tái cấu trúc EP01 (25 - 30 phút).

---

## I. TỔNG QUAN HIỆN TRẠNG PIPELINE VÀ CẤU TRÚC HỆ THỐNG

### 1. Kiến Trúc Thư Mục & Phân Phối Trách Nhiệm
Dự án được cấu trúc rõ ràng theo chuẩn sản xuất điện ảnh kỹ thuật số:
- `AGENTS.md` & `GEMINI.md`: Chỉ thị kỹ thuật tối cao. Quy định bắt buộc:
  - Phiên duyệt ngầm: `agent-browser --session muse` (Profile 5 Phu2234).
  - Tường lửa âm thanh (Audio Guard): Cấm tuyệt đối nhạc nền ngẫu nhiên trong từng shot; chỉ cho phép foley, ambience, và thoại.
  - Cấm OpenCV concat: Bắt buộc dùng FFmpeg `filter_complex concat` (`[v][a]`) bảo toàn AAC 48kHz.
  - Tiêu chuẩn xuất bản: EBU R128 Integrated `-14 LUFS (±0.5)`, True Peak `-1.0 dBTP`.
- `00_Project_Bible/CINEMATIC_AUDIO_PIPELINE.md`: Bản đặc tả chi tiết kiến trúc âm thanh 4 lớp (4-Stem Architecture), quy trình 6 bước hậu kỳ, và chỉ thị prompt.
- `05_Production_Pipeline/`:
  - `production_orchestrator.py`: Điều phối sản xuất shot, batch scene, concat master, và audio master.
  - `run_shot.py`: Script tự động hóa render 6 bước trên trình duyệt với Muse.ai.
  - `audio_continuity_engine.py`: Động cơ xử lý âm thanh (volumedetect, acrossfade, loudnorm, dynamic ducking).
  - `continuity_checker.py`: Kiểm tra tính liên tục thị giác giữa 2 shot bằng Histogram màu HSV và Structural Template Match.
  - `assemble_ep01_feature.py`: Script ghép nối 14 cảnh hiện tại thành master tập 1 (~7m30s - 10min).
  - `pipeline_helper.py`: Trợ lý trích xuất prompt và thống kê tài nguyên.
- `04_Assets/`:
  - `videos/`: Chứa 150+ video mp4 (các shot 10s raw và các bản master cảnh ghép nối).
  - `keyframes/`: Chứa tail frames (`clean_frame_239.jpg`) làm start frames cho shot kế tiếp.
  - `characters/`: Chứa ảnh nhân vật 720p I2V và master portraits.
  - `audio/`: Chứa `scene01_bgm.m4a` (hiện chỉ có 1 file BGM cho cảnh 1).
  - `audio_sfx/`: Thư mục rỗng (chưa có thư viện hiệu ứng âm thanh độc lập).
  - `archive/audio/`: Chứa các bản thu thoại thử nghiệm đã lưu trữ làm bằng chứng IP.
- `06_Exports/`: Chứa 90+ bản video xuất bản (cinematic masters của từng cảnh, các bản Grand Feature Master và Roadshow đa tập).
- `web_review/`:
  - `server.py`: FastAPI server chạy tại `0.0.0.0:1515`.
  - `templates/index.html`: Giao diện Web Review Studio điện ảnh sang trọng, kết nối từ xa qua Tailscale IP `http://100.121.197.18:1515`.

---

## II. KHẢO SÁT CHUYÊN SÂU R6: 4-STEM AUDIO & TÍNH LIÊN TỤC CỦA ÂM CẢNH (AMBIENCE CONTINUITY)

### 1. Kiến Trúc 4 Lớp Âm Thanh: Đặc Tả vs. Triển Khai Thực Tế

| Tầng Âm Thanh (Stem) | Quy Chuẩn Trong Project Bible | Triển Khai Hiện Tại Trong Code | Đánh Giá Khoảng Trống (Gap) |
| :--- | :--- | :--- | :--- |
| **Stem 1: BGM & Score** | Nhạc nền cổ phong ngũ cung kết hợp giao hưởng, trải thảm liên tục 50s - 180s/scene, EQ notch 800Hz - 3.5kHz. | Chỉ hỗ trợ qua tham số `--bgm` trong `master_scene_audio()`. Có hàm `layer_bgm_with_ducking`. | **Một phần**: Đã có ducking cơ bản, nhưng chưa có EQ notch filter tự động. Kho tài nguyên mới chỉ có `scene01_bgm.m4a`. |
| **Stem 2: Ambience & Soundscape** | Âm cảnh 3D vật lý (đám đông trẩy hội, gió liễu, suối ngọc, tiếng ve), stereo panning, trải dài liên tục dưới toàn bộ scene. | **Hoàn toàn vắng bóng** như một track độc lập. Dựa hoàn toàn vào âm thanh ngẫu nhiên do Muse.ai tự sinh trong từng shot 10s. | **Nghiêm trọng (Critical)**: Nguyên nhân gốc rễ gây đứt gãy tiếng ồn đám đông hội xuân giữa các shot. |
| **Stem 3: Foley & SFX** | Tiếng áo lụa Giao Lĩnh, trâm ngọc va chạm, tách trà sứ, vó ngựa, gươm đao. | Phụ thuộc 100% vào foley do Muse sinh ra trong shot; thư mục `04_Assets/audio_sfx` rỗng. | **Thiếu**: Không có thư viện spot foley rời để bù đắp khi Muse.ai sinh thiếu tiếng. |
| **Stem 4: Dialogue & Voice-Over** | Thoại nhân vật & ngâm thơ Kiều. Vocal chain: De-ess, low-cut 80Hz, warmth EQ 150-250Hz, sidechain ducking BGM -14dB. | Chỉ có ducking sidechain dựa trên waveform của shot Muse.ai (`0:a`), không có pipeline nạp voice track rời chuẩn hóa. | **Thiếu**: Sidechain compressor lấy toàn bộ audio của Muse.ai làm trigger, nếu Muse có tiếng ồn to sẽ tự duck BGM sai thời điểm. |

### 2. Thực Nghiệm Định Lượng: Nguyên Nhân Gây Đứt Đoạn / Nhảy Âm Lượng Đám Đông Hội Xuân
Đã thực hiện audit thực nghiệm bằng `AudioContinuityEngine.inspect_sequence()` trên các shot thực tế của Scene 4 và Scene 5 (Phân cảnh Hội Đạp Thanh / Thanh Minh):

#### Kết quả Scene 4 (`ep01_scene04_shot01` vs `shot02`):
- Shot 01: Max `-5.2 dB` | Mean: `-26.9 dB`
- Shot 02: Max `-7.0 dB` | Mean: `-30.0 dB`
- **Độ chênh lệch**: `3.1 dB` (Hệ thống phát cảnh báo lệch âm lượng cần normalize).

#### Kết quả Scene 5 (`ep01_scene05_shot01` đến `shot06`):
```
[1] ep01_scene05_shot01_10s.mp4 | Max:  -7.6 dB | Mean: -31.7 dB
[2] ep01_scene05_shot02_10s.mp4 | Max:  -0.0 dB | Mean: -16.3 dB  --> ⚠️ CHÊNH 15.4 dB (Đột biến âm lượng cực mạnh)
[3] ep01_scene05_shot03_10s.mp4 | Max:  -4.1 dB | Mean: -21.8 dB  --> ⚠️ CHÊNH 5.5 dB
[4] ep01_scene05_shot04_10s.mp4 | Max: -11.6 dB | Mean: -36.5 dB  --> ⚠️ CHÊNH 14.7 dB (Rơi thẳng vào gần câm lặng)
[5] ep01_scene05_shot05_10s.mp4 | Max:  -6.0 dB | Mean: -25.2 dB  --> ⚠️ CHÊNH 11.3 dB (Bật to trở lại)
[6] ep01_scene05_shot06_10s.mp4 | Max:  -4.6 dB | Mean: -25.4 dB  --> ✓ Chênh an toàn 0.2 dB
```

#### 4 Nguyên Nhân Cốt Lõi Khiến Âm Cảnh Bị Giật Cụt & Đứt Đoạn:
1. **Sự Biến Thiên Ngẫu Nhiên Của Động Cơ AI (Muse.ai Generative Variance)**:
   Mỗi shot 10s được render độc lập. Muse.ai sinh âm thanh mà không có bộ nhớ ngữ cảnh về mức âm lượng hay dải tần của shot đứng trước. Ở Shot 1 âm lượng trung bình là -31.7 dB, sang Shot 2 đột ngột bùng nổ lên -16.3 dB (tăng gấp đôi năng lượng âm thanh), rồi đến Shot 4 tụt sâu xuống -36.5 dB (chênh lệch cực đại giữa Shot 2 và Shot 4 lên tới 20.2 dB!).
2. **Quy Trình Ghép Nối Dùng Hard Concat Thay Vì Crossfade**:
   Trong `production_orchestrator.py` (dòng 348 - 351), hàm `concat_scene_shots()` sử dụng:
   ```python
   concat_filter = f"{''.join(filter_parts)}concat=n={n}:v=1:a=1[v][a]"
   ```
   Lệnh này nối trực tiếp đuôi âm thanh shot N vào đầu shot N+1 bằng phép cắt cứng (hard cut). Do năng lượng âm cảnh không đồng pha và mức dB chênh lệch tới 15.4 dB, điểm nối tại giây thứ 10, 20, 30... tạo ra tiếng "bụp" (click/pop) và cảm giác âm thanh đám đông bị giật cụt, ngắt quãng đột ngột.
3. **Bỏ Quên Động Cơ Crossfade Có Sẵn**:
   `audio_continuity_engine.py` đã viết sẵn hàm `stitch_with_audio_crossfade()` (với thuật toán `acrossfade=d=1.0:c1=qsin:c2=qsin`), nhưng `production_orchestrator.py` lại **chưa gọi hàm này** trong luồng xử lý chính `concat_scene_shots()`.
4. **Thiếu Lớp Âm Cảnh Trải Thảm Độc Lập (Stem 2 Soundscape Bed)**:
   Trong điện ảnh chuyên nghiệp, âm thanh không khí lễ hội (tiếng xôn xao, cười nói, gió xuân) không bao giờ phụ thuộc vào mic thu tại shot ngắn. Nó bắt buộc phải là một track stereo Ambience trải dài liên tục từ đầu đến cuối phân cảnh (50s - 180s). Khi thiếu track Stem 2 này, mọi khuyết tật âm thanh của video AI đều bị phơi bày trực tiếp trước tai người nghe.

### 3. Khảo Sát Tiêu Chuẩn EBU R128 (-14 LUFS) & YouTube Green Dollar

#### Cơ Chế Hiện Tại
`audio_continuity_engine.py` sử dụng bộ lọc FFmpeg:
```bash
-af loudnorm=I=-14.0:TP=-1.0:LRA=9.0
```

#### Đo Lường Thực Tế Bằng `ebur128=peak=true` Trên Master Scene 1
Đã đo kiểm file `06_Exports/ep01_scene01_cinematic_master.mp4`:
- **Integrated Loudness đo được**: `I: -12.9 LUFS` (Mục tiêu: `-14.0 LUFS`).
  *Nhận xét*: Bị to hơn tiêu chuẩn 1.1 LUFS!
- **True Peak**: `Peak: -1.0 dBFS` (Đạt chuẩn chính xác 100%).
- **Loudness Range**: `LRA: 4.6 LU` (Mục tiêu: 9.0 LU).

#### Nguyên Nhân Lệch Chuẩn
- Bộ lọc `loudnorm` hiện chạy ở chế độ **Single-Pass (1-Pass dynamic)**. Ở chế độ này, FFmpeg phải ước tính gain trên một cửa sổ trượt (lookahead), dễ bị trôi độ lớn tích hợp (Integrated Loudness) khi cảnh có nhiều đoạn tĩnh hoặc nốt đàn ngắt quãng.
- Để đạt chuẩn phát sóng khắt khe của YouTube Green Dollar và Netflix mà không bị phạt nén âm lượng (penalty attenuation), cần chuyển sang quy trình **Two-Pass EBU R128**:
  - *Pass 1*: Quét phân tích toàn bộ audio stream để lấy JSON: `measured_I`, `measured_TP`, `measured_LRA`, `measured_thresh`, `offset`.
  - *Pass 2*: Chuẩn hóa tuyến tính (linear=true) áp dụng đúng các tham số đã đo, đảm bảo kết quả đầu ra đạt chuẩn xác `-14.0 LUFS (±0.1)`.
- Khi ghép toàn tập bằng `assemble_ep01_feature.py`, script này hoàn toàn không áp dụng bộ lọc `loudnorm` cho file master cuối cùng.

---

## III. KHẢO SÁT CHUYÊN SÂU R7: TỰ ĐỘNG HÓA SẢN XUẤT & WEB REVIEW STUDIO (PORT 1515)

### 1. Kiến Trúc & Vận Hành Web Review Studio
- **Mã nguồn**: `web_review/server.py` và `web_review/templates/index.html`.
- **Cổng dịch vụ & Tailscale**: Chạy qua `uvicorn.run(app, host="0.0.0.0", port=1515)`. Nhờ gán `0.0.0.0`, server mở cổng cho tất cả interface mạng, bao gồm mạng riêng ảo Tailscale tại IP `100.121.197.18:1515`. Người dùng có thể duyệt từ xa qua điện thoại/tablet/máy tính cá nhân.
- **Tĩnh & Dữ Liệu Video**:
  - Mount `/assets/videos` trỏ về `04_Assets/videos`.
  - Mount `/assets/exports` trỏ về `06_Exports`.
  - Mount `/assets/characters` trỏ về `04_Assets/characters`.
  - Mount `/assets/keyframes` trỏ về `04_Assets/keyframes`.

### 2. Cơ Chế Tự Động Quét & Đăng Ký Video Mới (Auto-Discovery)
Hàm `build_library_data()` trong `web_review/server.py` quét tự động:
1. `EXPORTS_DIR.rglob("*.mp4")`:
   - Nếu tên chứa `ep01_to_ep06` hoặc `roadshow` hoặc `continuous_master` -> Xếp vào `feature_masters`.
   - Nếu tên chứa `grand_feature_master` -> Xếp vào `episode_masters` (ví dụ: `thap_ngu_nien_ep01_grand_feature_master_*.mp4`).
   - Nếu tên chứa `cinematic_master` hoặc (`master` và `scene`) -> Xếp vào `scene_masters` theo Tập và Cảnh.
   - Nếu tên chứa `9x16` hoặc `shorts` -> Xếp vào `shorts`.
2. `VIDEOS_DIR.glob("*.mp4")`:
   - Phân tích regex: `ep0?(\d+)`, `scene0?(\d+)`, `shot0?(\d+)`.
   - Gom nhóm thành các phân cảnh: `ep01_sceneXX` chứa các shot `ep01_sceneXX_shotYY_10s.mp4`.
3. Bộ nhớ đệm (Cache): Hết hạn sau **3 giây** (`now - _cache_time < 3.0`).
4. **Kết luận Auto-Registration**: Bất kỳ khi nào pipeline render một shot mới vào `04_Assets/videos/` hoặc xuất master mới vào `06_Exports/`, Web Studio **tự động phát hiện và hiển thị ngay lập tức** trong vòng 3 giây mà không cần khởi động lại server.

### 3. Tự Động Hóa Muse.ai & Chuỗi Head-Tail (I2V Chaining)
- **Phiên trình duyệt cố định**: `agent-browser --session muse` gắn liền với Google Chrome Profile 5 (Phu2234), đã lưu phiên đăng nhập và credit tài khoản.
- **Quy trình 6 bước trong `run_shot.py`**:
  1. Upload Start Frame qua `agent-browser --session muse upload "input[type=file]" "<path>"`.
  2. Bổ sung chuỗi Audio Guard chống nhạc rác.
  3. Tìm ô chat bằng regex động `textbox "Nhắn tin" [ref=...]` (hoặc fallback `@e14`) và điền prompt.
  4. Xác định nút Gửi động `button "Gửi" [ref=...]` hoặc Enter.
  5. Giám sát trạng thái qua snapshot ngầm (`agent-browser --session muse snapshot -i`), đợi nút `button "Tải video xuống" [ref=...]` mới.
  6. Tải về `~/Downloads/`, di chuyển vào `04_Assets/videos/<shot_id>_10s.mp4`.
  7. Trích xuất Tail Frame (frame 239) qua OpenCV lưu vào `04_Assets/keyframes/<shot_id>/clean_frame_239.jpg`.
  8. Kiểm tra tính liên tục thị giác qua `continuity_checker.py`.

### 4. Bất Cập Phát Hiện Trong Web Review Studio (`web_review/server.py`)
So sánh giữa `run_shot.py` và `web_review/server.py`:
- Trong `server.py` (dòng 476 - 477), hàm `run_agent_browser_generation()` đang dùng các selector cố định lỗi thời:
  ```python
  subprocess.run(["agent-browser", "--session", "muse", "fill", "@e14", prompt], ...)
  subprocess.run(["agent-browser", "--session", "muse", "click", "@e51"], ...)
  ```
- **Rủi ro**: Nếu bấm "Tạo Video" từ giao diện Web Studio:
  - Không upload ảnh Start Frame.
  - Không tự chèn Audio Guard.
  - `@e51` là ref cứng có thể bị trôi khi DOM thay đổi, dẫn đến prompt không được gửi.
  - Không trích xuất Tail Frame `clean_frame_239.jpg`.
- **Cần khắc phục**: Đồng bộ hóa logic của `run_agent_browser_generation()` trong `server.py` với `run_shot.py` hoặc gọi trực tiếp `run_shot_pipeline()`.

---

## IV. KẾ HOẠCH CẬP NHẬT KỸ THUẬT & SỬA ĐỔI SCRIPT CHO EP01 (25 - 30 PHÚT)

### 1. Nâng Cấp `audio_continuity_engine.py`
1. **Tiền Chuẩn Hóa Gain Staging Từng Shot (Per-Shot RMS Normalization)**:
   - Trước khi nối, đo `mean_volume` của từng shot.
   - Cân bằng tự động về mức chuẩn chung (ví dụ: `-24.0 dB`) bằng bộ lọc `volume` trước khi đưa vào crossfade, triệt tiêu hoàn toàn cú sốc nhảy 15.4 dB.
2. **Triển Khai Động Cơ Hòa Âm 4 Lớp Hoàn Chỉnh (`mix_4_stem_scene`)**:
   - Nhận đầu vào: `video_concat`, `bgm_track` (Stem 1), `ambience_bed` (Stem 2), `foley_track` (Stem 3), `voice_track` (Stem 4).
   - Thiết lập bộ lọc EQ notch cho BGM (khoét 800Hz - 3.5kHz giảm -3dB).
   - Sidechain ducking: Khi có voice ở Stem 4, tự động hạ cả BGM (Stem 1) và Ambience (Stem 2) `-14 dB` (attack 50ms, release 300ms).
3. **Triển Khai Two-Pass EBU R128 Master**:
   - Thêm phương thức `normalize_loudness_2pass()` đo kiểm Pass 1 và render Pass 2 tuyến tính, đạt chuẩn chính xác `-14.0 LUFS (±0.1)`.

### 2. Nâng Cấp `production_orchestrator.py`
1. **Thay Thế Hard Concat Bằng Audio Crossfade Mặc Định**:
   - Trong `concat_scene_shots()`: Chuyển từ lệnh `concat=n=N:v=1:a=1` sang sử dụng `AudioContinuityEngine.stitch_with_audio_crossfade()` với `acrossfade=d=1.0:c1=qsin:c2=qsin`.
2. **Tích Hợp Tiền Kiểm Tra Delta Âm Lượng Trong Batch Render**:
   - Trong `batch_render_scene()`: Tự động chạy `inspect_sequence()` trước khi concat. Nếu phát hiện delta > 3.0 dB, tự động kích hoạt bộ cân bằng gain staging.
3. **Mở Rộng Lệnh CLI `--master-audio`**:
   - Bổ sung các cờ: `--ambience <path>`, `--foley <path>`, `--voice <path>` để kích hoạt bộ hòa âm 4 lớp.

### 3. Nâng Cấp `assemble_ep01_feature.py` Phục Vụ 25 - 30 Phút
1. **Cấu Trúc Lại Danh Sách Cảnh Mở Rộng**:
   - Mở rộng từ 14 cảnh ngắn lên chuỗi phân cảnh đầy đủ đạt 25 - 30 phút (bao gồm phân đoạn Mộ Đạm Tiên 3 nhịp cảm xúc, Kim Trọng nhặt trâm, không gian Vương gia tĩnh lặng).
2. **Audio Transition Bridge Giữa Các Scene**:
   - Áp dụng kỹ thuật chuyển cảnh âm thanh (Audio Crossfade / Bridge 1.5s - 2.0s) giữa các Cảnh để không bị khựng âm không gian khi chuyển từ phố hội ồn ào sang đồng hoang mộ vắng.
3. **Two-Pass Master Toàn Tập**:
   - Chạy chuẩn hóa 2-pass EBU R128 cho toàn bộ file xuất xưởng `thap_ngu_nien_ep01_grand_feature_master_30min.mp4`.

### 4. Nâng Cấp `web_review/server.py`
1. **Chuẩn Hóa Bộ Kích Hoạt Sinh Video**:
   - Thay thế các ref tĩnh `@e14`, `@e51` bằng logic gọi trực tiếp module `run_shot.py`.
   - Hỗ trợ truyền `start_frame` từ giao diện Web Studio sang Muse.ai.
2. **Thêm API Điều Phối Sản Xuất (Orchestrator Endpoints)**:
   - `POST /api/orchestrator/concat-scene`: Ghép master cảnh từ xa.
   - `POST /api/orchestrator/master-audio`: Master âm thanh 4 lớp từ xa.
   - `GET /api/orchestrator/status`: Trả về tiến độ render thực tế theo thời gian thực.

---

## V. MA TRẬN LỆNH KIỂM CHỨNG ĐỘC LẬP (VERIFICATION RUNBOOK)

Sau khi đội ngũ triển khai thực hiện cập nhật mã nguồn, các câu lệnh sau sẽ được dùng để kiểm chứng:

```bash
# 1. Kiểm tra tiến độ tổng thể của toàn bộ hệ thống sản xuất:
python "05_Production_Pipeline\production_orchestrator.py" --status

# 2. Kiểm tra độ đồng nhất âm thanh của một phân cảnh bất kỳ (phát hiện lệch dB):
python -c "import sys, glob; sys.path.append('05_Production_Pipeline'); from audio_continuity_engine import AudioContinuityEngine; engine = AudioContinuityEngine(); shots = sorted(glob.glob('04_Assets/videos/ep01_scene05_shot*.mp4')); engine.inspect_sequence(shots)"

# 3. Đo kiểm chỉ số EBU R128 thực tế của Master video:
ffmpeg -i "06_Exports/ep01_scene01_cinematic_master.mp4" -filter_complex ebur128=peak=true -f null -

# 4. Kiểm tra khả năng phục vụ của Web Review Studio trên cổng 1515:
# (Khởi chạy server)
python "web_review\server.py"

# (Kiểm tra API trên terminal khác)
curl http://localhost:1515/api/library
curl http://100.121.197.18:1515/api/status
```

---
*Báo cáo được hoàn thành bởi teamwork_preview_explorer.*
