# ๐ŸŽ‰ ap_ds AFS 0.0.1-AFS Pre-release โ€” The Permanent Home of Opus Support --- ## ๐Ÿ”ง Version 0.0.1a3 โ€” Bug Fix Announcement Welcome to **0.0.1a3**! This release fixes several issues found in the previous version (0.0.1a2), focused mainly on the Opus playback engine, metadata parsing and packaging. ### โœ… What's Fixed in This Release **Opus playback engine (`opusplayer.py`)** - **Fade worker indentation** โ€” `_fade_worker` was accidentally defined outside the `OpusAudio` class, causing `AttributeError` on `fadeout/fadein/fadein_pos`. It is now a proper class method. - **Fade-in now stops and restarts** โ€” `fadein_music` previously refused to run while playing ("Already playing"). It now stops any current playback first, starts a fresh AID, then fades in. - **Seek now truly jumps** โ€” `seek_audio` previously only moved the stream position without resetting the buffered audio, so jumps were not audible. It now restarts the playback thread from the new position. - **Seek resumes after fade-out** โ€” seeking now always restarts playback, even after a fade-out had stopped it. - **Fade-out restores volume** โ€” the volume was being reset to 0 after fade-out, making any later play/seek/fade-in silent. The normal volume is now restored after fade-out. - **Boundary robustness** โ€” `fadein_music(ms=None)`, `fadeout_music(None)` and `fadein_music_pos(position=None)` no longer crash with a TypeError; invalid values fall back safely to defaults or return an error tuple. **Opus metadata parsing (`audio_parser.py`)** - `open_audio(.opus)` no longer raises `ValueError`. A new `OPUSFile` parser delegates to `opusplayer`, so `get_audio_duration`, `get_audio_metadata` and `batch_get_metadata` all support Opus files. - Directory scanning for `batch_get_metadata` now includes `.opus`. **Audio library routing (`player.py`)** - `get_audio_metadata_by_aid()` now routes Opus AIDs to the `OpusAudio` engine, returning consistent metadata. **Packaging** - Restored the main `ap_ds/__init__.py` (its exported functions had been accidentally replaced, which omitted all top-level APIs from the built package). All public APIs are exported again. **Tests** - CI/CD fade duration increased to 5s for a clearer audible effect. - Added `test_opus_interactive.py` for manual Opus playback / seek / fade verification. ### ๐Ÿ™ Keep Reporting Bugs We truly value your feedback. If you encounter any issue while using the library, please don't hesitate to submit a bug report. Together we'll keep polishing the product: ๐Ÿ“ง **Where to send (please CC both addresses to guarantee delivery):** - **me@dvsyun.top** (primary) - **dvs6666@163.com** (backup) โฑ๏ธ **Our promise:** we will fix reported issues within **3 business days**. To help us resolve issues faster, please include the following when submitting a bug report: - Operating system and version - Python version (`python --version`) - The full error message - Reproduction steps - A sample audio file (if possible) Every single piece of feedback drives us forward. ๐ŸŽ‰ โš ๏ธ **Important:** 0.0.1-AFS is a **pre-release test version** for feedback collection and bug reporting. The first stable release **1.0.0** is planned for **September 2026**. This is the first release of the **AFS (All Format Support)** branch โ€” a standalone fork of ap_ds ecosystem built specifically for **Opus** and all future new formats, with **permanent support commitment**. If you encounter any issues, please contact us immediately: ๐Ÿ“ง **Primary:** me@dvsyun.top ๐Ÿ“ง **Backup:** dvs6666@163.com โฑ๏ธ **We guarantee:** Fix within 3 business days Your feedback is crucial! Together, let's polish Opus support to perfection. > "We don't just support a new format โ€” we open the door to higher quality, smaller size, and greater freedom." โ€” DVS Development Team, August 2026 --- ## ๐Ÿ“ฆ Installation ### Install the Package ```bash # AFS pre-release (includes Opus, for testing feedback) pip install ap-ds-afs==0.0.1a3 # AFS stable release (coming September 2026) pip install ap-ds-afs==1.0.0 ``` ### Import โ€” Same as Always! **No matter which package you installed** (`ap-ds` or `ap-ds-afs`), the import is **exactly the same**: ```python from ap_ds import AudioLibrary ``` โœ… Zero migration cost โ€” just change the package name in `requirements.txt` โœ… No code changes needed โ€” your existing code works as-is ### ๐Ÿ›ก๏ธ Foolproof Design โ€” Conflict Detection If a user accidentally installs **both** `ap-ds` and `ap-ds-afs` simultaneously, the library detects the conflict and **exits immediately** with a clear message: ```python >>> import ap_ds Checking for package conflicts... WARNING: Package conflict detected! The following packages exist simultaneously: - ap-ds and ap-ds-afs Please uninstall one of them. # Python process exits directly ๐Ÿ’€ ``` This is **not a bug** โ€” it's a **foolproof design** to prevent hard-to-debug import issues caused by conflicting packages. --- ## ๐Ÿš€ Quick Start Guide ### Basic Audio Playback ```python from ap_ds import AudioLibrary # Initialize the library lib = AudioLibrary() # Play an audio file aid = lib.play_from_file("music/song.mp3") # Control playback lib.pause_audio(aid) # Pause lib.play_audio(aid) # Resume lib.seek_audio(aid, 30.5) # Seek to 30.5s lib.set_volume(aid, 80) # Set volume (0-128) # Stop and get elapsed time elapsed = lib.stop_audio(aid) print(f"Played {elapsed:.2f} seconds") ``` ### Playing Opus Files (via AudioLibrary โ€” Recommended) ```python from ap_ds import AudioLibrary lib = AudioLibrary() aid = lib.play_from_file("song.opus") # Auto-routed to Opus engine # All control methods are identical lib.pause_audio(aid) lib.seek_audio(aid, 30.0) lib.set_volume(aid, 80) lib.stop_audio(aid) ``` ### Playing Opus Files (Directly Using OpusAudio) ```python from ap_ds import OpusAudio opus = OpusAudio() aid = opus.play_from_file("song.opus") opus.pause_audio(aid) opus.seek_audio(aid, 30.0) opus.stop_audio(aid) ``` ### Getting Audio Metadata ```python from ap_ds import get_audio_metadata meta = get_audio_metadata("song.opus") print(meta["duration"]) # 265 print(meta["sample_rate"]) # 48000 print(meta["channels"]) # 2 print(meta["bitrate"]) # 105351 ``` ### Batch Parsing (Parallel Processing) ```python from ap_ds import batch_get_metadata # Parse 120 MP3s in just 0.33 seconds! results = batch_get_metadata("/music/playlist/", max_workers=8) for meta in results: print(f"{meta['path']}: {meta['duration']}s, {meta['bitrate']}bps") ``` **โš ๏ธ Windows Users:** You MUST protect your entry point with `if __name__ == "__main__"`: ```python from ap_ds import batch_get_metadata def main(): results = batch_get_metadata("/music/", max_workers=4) print(f"Parsed {len(results)} files") if __name__ == "__main__": main() ``` ### DAP Playlist System ```python # Files are recorded automatically into DAP (DVS Audio Playlist) aid1 = lib.play_from_file("song1.mp3") aid2 = lib.play_from_file("song2.ogg") # Get all recordings recordings = lib.get_dap_recordings() print(f"Recorded {len(recordings)} files") # Save as JSON lib.save_dap_to_json("my_playlist.ap-ds-dap") ``` DAP stores only metadata (path, duration, bitrate, channels), not audio data. Each record takes approximately 150 bytes of memory. --- ## ๐Ÿ“ข A Letter to All Audio Developers Friends, colleagues, music lovers, and everyone who has ever stayed up late wrestling with audio formats: Today, we announce โ€” **ap_ds AFS 0.0.1-AFS** is officially released! The **AFS (All Format Support)** branch makes its debut, providing **permanent support** for the Opus audio format for the first time! But before excitement takes over, we must be honest with you: **This is a pre-release version.** What does that mean? It means: โœ… All core features are implemented and tested โœ… 229 Opus-specific tests all pass โœ… Cross-platform (Windows/Linux/macOS) playback verified โš ๏ธ Some edge-case bugs may still exist that we haven't found โš ๏ธ We need real users to test in diverse environments So we're giving this version to **you** โ€” our users โ€” to help us test. > **"AFS is the permanent home of Opus and all future new formats."** This is part of ap_ds's dual-track strategy. We'll explain in detail in the following sections. --- ## ๐Ÿšจ Important Notes on Version 0.0.1-AFS Positioning ### 1. This is a Pre-release 0.0.1-AFS is **not** an LTS or final stable version. It is a **pre-release** aimed at: - Collecting real-world usage feedback - Discovering edge-case bugs not covered by tests - Verifying cross-platform compatibility - Gathering data for the 1.0.0 stable release ### 2. AFS Branch โ€” The Permanent Home of Opus This is a critical statement: **The AFS branch is the permanent home for Opus and all future new formats.** Unlike the mainline (`ap-ds` 4.x), the AFS branch will **permanently retain** Opus support and continuously add new formats. | Version | Opus Support | Description | |---------|-------------|-------------| | 0.0.1-AFS | โœ… Yes | First AFS pre-release | | 1.0.0 (Sep 2026) | โœ… Yes | First AFS stable release | | Future AFS | โœ… Yes | Permanent support | | Mainline 4.2.0+ | โŒ No | Returns to lightweight positioning | **Why?** Because ap_ds mainline's core promise is **2.5MB lightweight**. Opus support (including DLLs) pushes the size to ~3.87MB. Mainline will remove Opus to return to 2.5MB. The AFS branch is specifically designed to carry Opus and future formats, at ~2.8-3.5MB. So if you need Opus support: - **Short-term testing:** Use 0.0.1-AFS pre-release - **Long-term use:** Use AFS branch (`pip install ap-ds-afs`), with 1.0.0 stable coming in September - Both packages use **identical imports** (`from ap_ds import AudioLibrary`) โ€” zero migration cost ### 3. Bug Reporting & Fix Commitment If you find any issues with 0.0.1-AFS: ๐Ÿ“ง me@dvsyun.top ๐Ÿ“ง dvs6666@163.com (CC both for delivery guarantee) **We promise:** - Fix within **3 business days** - Patch releases will be published promptly **When reporting, please provide:** - OS and version - Python version (`python --version`) - Full error message (if any) - Reproduction steps - Audio file sample (if possible) Every piece of feedback helps us build a better ap_ds. ๐Ÿ™ --- ## ๐Ÿค” Why Opus? โ€” The Technical Imperative ### 1. Quality & Compression Ceiling Opus is an open audio codec jointly developed by the Xiph.Org Foundation and IETF, combining SILK (speech) and CELT (general audio) algorithms with adaptive bitrate from 6 kbps to 510 kbps. This means: - At low bitrates (<32 kbps), Opus voice clarity far exceeds MP3 and AAC - At medium-high bitrates (64-128 kbps), Opus quality matches or exceeds MP3 at 320kbps - Ultra-low latency (as low as 5ms), ideal for real-time communication and gaming ### 2. Open Source & Freedom โ€” A Philosophical Fit Opus uses a BSD-like license with **no patent restrictions**, completely free. This aligns perfectly with ap_ds's commitment to openness, freedom, and zero burden. ### 3. Mature Ecosystem & Clear Demand Opus is widely used in: - **WebRTC** (real-time audio/video communication) - **Discord, WhatsApp, Signal** and other instant messaging apps - **Game engines** (Unity, Unreal both support Opus) - **Audio streaming** (broadcasting, podcasting) - **Embedded devices** (low power, high compression) As more audio content is published in Opus format, ap_ds as a general-purpose audio library must respond to this trend. ### 4. Paving the Way for the AFS Branch Opus is the first member of the AFS (All Format Support) branch. Through the 0.0.1-AFS pre-release, we validate cross-platform Opus playback solutions and accumulate experience for the 1.0.0 stable release. --- ## ๐Ÿ˜… Why Didn't We Support Opus Before? โ€” The Upstream Dependency Story This is a great question. Honestly, we've wanted to support Opus since ap_ds v1.0. But the reality is: ap_ds has always relied on **SDL2 and SDL2_mixer** for audio playback. SDL2 is an excellent cross-platform multimedia library that handles audio device abstraction, mixing, and buffering across Windows, macOS, and Linux. SDL2_mixer supports MP3, WAV, OGG, FLAC and other formats out of the box. But the problem is โ€” **SDL2_mixer's Opus support was never stable enough.** | Platform | Issue | |----------|-------| | Windows | Official SDL2_mixer Windows binaries often lack Opus support or have incomplete compile flags, causing `Mix_LoadMUS` to return NULL for `.opus` files | | macOS | SDL2_mixer Framework builds frequently have version mismatches and `libopusfile`/`libogg` dependency issues, causing runtime crashes | | Linux | SDL2_mixer depends on system-installed `libopusfile-dev`, but package names and versions vary widely across distributions | | API Inconsistency | Even when Opus loads, SDL2_mixer's metadata extraction (duration, bitrate, etc.) often returns 0 or errors | We tried multiple approaches: - Compiling our own Opus-enabled SDL2_mixer binaries โ†’ Bloated, high maintenance cost - Forcing users to install `libopusfile-dev` on Linux โ†’ Poor UX, and Windows/macOS issues remained - Waiting for upstream SDL2_mixer fixes across multiple versions โ†’ Issues persisted **Conclusion:** SDL2_mixer's upstream support was insufficient to provide stable Opus playback. Therefore, before AFS, we made a difficult decision โ€” **temporarily not support Opus** to avoid giving users an unstable experience. ### How Does 0.0.1-AFS Solve This? **Because SDL2 doesn't work, we decided to not use SDL2 at all!** In the AFS branch, we completely bypass SDL2 and SDL2_mixer, building a **dedicated playback pipeline** for Opus: ``` User passes .opus file โ†“ Detects .opus extension โ†“ libopusfile decodes โ†“ Cross-platform audio output engine โ”œโ”€โ”€ Windows โ†’ winmm waveOut โ”œโ”€โ”€ Linux โ†’ ALSA (libasound.so) โ””โ”€โ”€ macOS โ†’ Core Audio AudioQueue โ†“ Audio output to speakers ``` This pipeline is **completely independent of SDL2**, free from SDL2_mixer's limitations. Meanwhile, Windows users don't need to hunt for DLLs โ€” ap_ds automatically downloads the required four DLLs (`libopusfile-0.dll`, `libopus-0.dll`, `libogg-0.dll`, `libopusurl-0.dll`) on first run with **SHA256 hash verification** ensuring file integrity. This is why AFS can support Opus, and why we couldn't before. It's not that we didn't want to โ€” we had to find a reliable, stable, truly cross-platform solution. Now we have one. --- ## ๐Ÿงฌ Technical Deep Dive โ€” What We Actually Did ### 1. New Modules & Architecture To integrate Opus support without affecting mainline stability, we carefully designed the project structure: | File | Responsibility | Description | |------|---------------|-------------| | `opusplayer.py` | Opus playback core | `OpusAudio` class โ€” fully independent of SDL2, encapsulates all Opus playback, control, metadata and batch APIs | | `_opusdll.py` | Opus library loader | Cross-platform loading (Windows auto-download, Linux/macOS system detection + install guide), unified libopusfile client | | `player.py` (modified) | Opus routing integration | `AudioLibrary` auto-detects `.opus` files and forwards to `OpusAudio` sub-player, fully transparent playback | | `__init__.py` (modified) | Export OpusAudio | Users can use `from ap_ds import OpusAudio` directly or seamlessly through `AudioLibrary` | **Key Design: AID 1:1 Mapping** When a user plays via `AudioLibrary.play_from_file("song.opus")`, the library internally creates an `OpusAudio` instance and generates a sub-AID, then maps the main library AID to the sub-library AID via a dictionary. All subsequent controls (pause, resume, volume, seek) route correctly to the Opus engine, completely transparent to user code. ```python # User code โ€” exactly the same as before! from ap_ds import AudioLibrary lib = AudioLibrary() aid = lib.play_from_file("song.opus") # Auto-routed to Opus engine lib.pause_audio(aid) # Auto-routed to Opus engine lib.seek_audio(aid, 30.0) # Auto-routed to Opus engine lib.stop_audio(aid) # Auto-routed to Opus engine ``` **Fully transparent, zero learning curve.** ### 2. Cross-Platform Playback Backends โ€” Three Platform Engines Rewritten for Opus Opus playback cannot rely on SDL2, so we decided to completely bypass SDL2 and use native OS audio APIs directly with `libopusfile` decoding. | Platform | Playback Solution | Tech Stack | |----------|------------------|------------| | **Windows** | winmm waveOut | libopusfile decode โ†’ waveOutWrite multi-buffer (4 buffers, 50ms/block) | | **Linux** | ALSA | libasound.so.2 โ†’ snd_pcm_open โ†’ snd_pcm_writei (direct PCM output) | | **macOS** | Core Audio AudioQueue | Apple official C API โ†’ AudioQueue callback fill (consistent with official examples) | **Platform Implementation Details:** **Windows** (`_play_worker_windows`): - Uses `waveOutOpen` to open default audio device - Uses `CreateEventW` + `WaitForSingleObject` for buffer completion synchronization - 4 buffers rotating to eliminate stuttering - `WAVEHDR` structure with `c_void_p` for 64-bit compatibility **Linux** (`_play_worker_linux`): - Uses `snd_pcm_open` with "default" device - Uses `snd_pcm_set_params` for PCM parameters (S16_LE, interleaved mode) - Uses `snd_pcm_writei` for PCM data write - On `-EPIPE` (buffer underrun), calls `snd_pcm_recover` for auto-recovery **macOS** (`_play_worker_macos`): - Uses `AudioQueueNewOutput` to create output queue - Uses `AudioQueueAllocateBuffer` for buffer allocation - Callback `HandleOutputBuffer` decodes Opus and fills `mAudioData` - Uses `AudioQueueStart` to start, `AudioQueueStop` to stop ### 3. Opus-Specific Error Codes (2001-2010) To make Opus-related errors clearer and more traceable, we added 10 dedicated error codes: | Code | Constant | Meaning | Suggested Action | |------|----------|---------|-----------------| | 2001 | AP_DS_ERR_OPUS_LIB_LOAD_FAILED | libopusfile load failed | Check DLL existence/locks | | 2002 | AP_DS_ERR_OPUS_DLL_DEPENDENCY | DLL dependency missing | Ensure libopus-0.dll and libogg-0.dll exist | | 2003 | AP_DS_ERR_OPUS_OPEN_FAILED | Opus file open failed | File may be corrupted or not valid Opus | | 2004 | AP_DS_ERR_OPUS_HEADER_CORRUPT | OpusHead header corrupt | Invalid or corrupted header info | | 2005 | AP_DS_ERR_OPUS_TAGS_PARSE_FAILED | Tag parse failed | Corrupted or invalid tag data | | 2006 | AP_DS_ERR_OPUS_DECODE_FAILED | Opus decode failed | Corrupted audio data | | 2007 | AP_DS_ERR_OPUS_SEEK_FAILED | Opus seek failed | Stream may not support seeking to this position | | 2008 | AP_DS_ERR_OPUS_BITRATE_UNAVAILABLE | Bitrate unavailable | Cannot determine bitrate for this Opus stream | | 2009 | AP_DS_ERR_OPUS_NOT_SEEKABLE | Stream not seekable | This Opus stream doesn't support seeking | | 2010 | AP_DS_ERR_OPUS_CHANNEL_INVALID | Invalid channel count | Invalid channel count in Opus stream | All Opus errors include: - Machine-readable error code (for programmatic handling) - Human-readable error message (for developer understanding) - Actionable suggestion (for user problem resolution) ### 4. Auto DLL Download & Hash Verification (Windows) Windows users don't need to manually find DLLs. When ap_ds first detects Opus support is needed, it: 1. Checks if the 4 required DLLs exist in the package directory 2. Downloads from `https://dvsyun.top/ap_ds/download/` if missing or hash verification fails 3. Performs SHA256 hash verification after download 4. Auto-retries if hash mismatch | File | Size | SHA256 | |------|------|--------| | libopusfile-0.dll | 55,884 B | fc8ff75c5e0180e73b0528dc78c51ed0fb493741375cdc227f50c2a33cabf727 | | libopus-0.dll | 500,112 B | 90aa25a0a6525d7da48a7ae8dd3306e45b0c28ce09a73d2a02b56cd95418d5be | | libogg-0.dll | 40,580 B | 3038ce8d161324a6349bf7c83b78493857ff6a3501e3adb3d541c6a07bd94a57 | | libopusurl-0.dll | 76,772 B | a6cde968a23f2d0067332a13718c52e265653a2c35d65862e8dff4cf2a0346d9 | ### 5. Cross-Platform Opus Library Loading **Windows:** - Check package directory for DLLs โ†’ Auto-download if missing โ†’ SHA256 verify โ†’ Load via `ctypes.CDLL` **Linux:** - User config check (`~/.config/ap_ds/opus_paths.conf`) โ†’ System library check (`ctypes.util.find_library("opusfile")`) โ†’ Auto-install (apt-get/dnf/pacman, interactive sudo) โ†’ Interactive setup **macOS:** - System library detection (find_library + common Homebrew/MacPorts paths) โ†’ MacPorts auto-install (`sudo port install opus opusfile libogg`) โ†’ Homebrew auto-install (`brew install opus opusfile libogg`) โ†’ Manual installation guide ### 6. OpusAudio Class โ€” Complete API The `OpusAudio` class provides an API nearly identical to `AudioLibrary`, but fully based on `libopusfile` and native audio output: | Method | Function | |--------|----------| | `play_from_file(file_path, loops=0, start_pos=0.0)` | Play Opus file | | `play_from_memory(file_path, loops=0, start_pos=0.0)` | Play from cache | | `new_aid(file_path)` | Preload Opus file | | `play_audio(aid)` | Resume playback | | `pause_audio(aid)` | Pause playback | | `stop_audio(aid)` | Stop playback, return elapsed time | | `seek_audio(aid, position)` | Seek to position (seconds) | | `set_volume(aid, volume)` | Set volume (0-128) | | `get_volume(aid)` | Get volume | | `fadein_music(aid, loops=-1, ms=0)` | Fade in during playback | | `fadein_music_pos(aid, loops=-1, ms=0, position=0.0)` | Fade in from position | | `fadeout_music(ms=0)` | Fade out and stop | | `is_music_playing()` | Check if playing | | `is_music_paused()` | Check if paused | | `get_music_fading()` | Get fade in/out status | | `get_audio_metadata(file_path)` | Get Opus metadata | | `get_audio_duration(file_path)` | Get Opus duration | | `get_audio_extended_metadata(file_path)` | Get extended tags (title/artist/album etc.) | | `batch_get_metadata(file_paths, max_workers=None)` | Batch parse Opus metadata | | `batch_get_duration(file_paths, max_workers=None)` | Batch get Opus duration | | `cleanup_function()` | Release all resources | ### 7. Library Size Changes Due to the addition of `opusplayer.py` (~45KB) and `_opusdll.py` (~25KB) plus Windows DLLs (~673KB total), this 0.0.1-AFS pre-release temporarily expands to ~3.87 MB. | Version | Opus Support | Size | Description | |---------|-------------|------|-------------| | 4.0.x | โŒ | ~2.5MB | Stable, no Opus | | **AFS 0.0.1-AFS** | โœ… | **~3.87MB** | **AFS pre-release with Opus** | | 4.2.0+ (mainline) | โŒ | ~2.5MB | Mainline returns to lightweight | | AFS 1.0.0+ | โœ… | ~2.8-3.5MB | AFS permanent home for Opus | --- ## ๐ŸŒฟ AFS Branch โ€” ap_ds's "Dual-Track" Future ### Why Split? With Opus added, the mainline package size grew from 2.5MB to 3.87MB. Every new format will increase size. If we stuff all formats into mainline, ap_ds will eventually become a bloated monster, betraying the original "lightweight" vision. **So we decided: split the family.** **AFS (All Format Support)** is a brand new independent branch that will carry all new format support, "beyond the 2.5MB limit." | Aspect | Mainline (ap-ds) | AFS Branch (ap-ds-afs) | |--------|-----------------|----------------------| | PyPI package | `ap-ds` | `ap-ds-afs` | | Import name | `ap_ds` | `ap_ds` (**identical!**) | | Version | 4.x (continues) | 0.0.1-AFS โ†’ 1.0.0+ | | Opus support | โŒ (except 4.1.0) | โœ… **Permanent** | | Core formats | MP3/WAV/FLAC/OGG/AAC | Same + Opus + all future formats | | Size | ~2.5MB | ~2.8-3.5MB | | Update strategy | Security fixes only | Mainline sync + own new formats | | Target users | Minimalist developers | Developers needing special formats | **Key Design: Same Import Name** ```python # Regardless of whether user installed ap-ds or ap-ds-afs # The import method is exactly the same! from ap_ds import AudioLibrary ``` This means users can switch between the two packages seamlessly by just changing the package name in `requirements.txt` or `pip install`. ### Which One Should You Choose? | Your Need | Recommendation | |-----------|---------------| | Only MP3/WAV/FLAC/OGG/AAC | Mainline (`ap-ds` 4.2.0+) โ€” lightweight, stable | | Need Opus, willing to test pre-release | AFS (`ap-ds-afs` 0.0.1-AFS) โ€” early adopter, feedback | | Need Opus, want long-term stability | AFS (`ap-ds-afs` 1.0.0, September 2026) โ€” full-featured, LTS | | Not sure about future format needs | Install mainline, switch to AFS later (same import!) | --- ## โš ๏ธ Windows Multiprocessing Warning If you're using ap_ds AFS 0.0.1-AFS on Windows... please read this carefully. Your program's ability to run depends on it. **What's the problem?** On Windows, Python's `multiprocessing` module uses the `spawn` method to create new processes. This means each child process re-imports your main module. If you call `batch_get_metadata()` or any batch function that uses `ProcessPoolExecutor` directly at the top level of your script, child processes will execute these calls again when re-importing, causing infinite recursion and eventually a `BrokenProcessPool` error. **Your program will crash. Directly.** **Affected APIs:** - `batch_get_metadata()` - `batch_get_duration()` - `batch_get_metadata_by_type()` - Opus batch parsing is also affected **How to fix?** Simply wrap your batch parsing code inside `if __name__ == "__main__":`. **โŒ Wrong (Will crash on Windows):** ```python from ap_ds import batch_get_metadata # This will crash directly on Windows! results = batch_get_metadata("/music/", max_workers=4) print(f"Parsed {len(results)} files") ``` **โœ… Correct:** ```python from ap_ds import batch_get_metadata def main(): results = batch_get_metadata("/music/", max_workers=4) print(f"Parsed {len(results)} files") if __name__ == "__main__": main() ``` **โœ… Correct (with config function):** ```python from ap_ds import batch_get_metadata def load_config(): return {"audio_dir": "/music/"} def main(): config = load_config() results = batch_get_metadata(config["audio_dir"], max_workers=4) print(f"Parsed {len(results)} files") if __name__ == "__main__": main() ``` **โœ… Jupyter Notebook Users:** Put the batch call inside a function, then execute it in a cell: ```python def run_batch(): from ap_ds import batch_get_metadata return batch_get_metadata("/music/", max_workers=4) results = run_batch() ``` **Why don't Linux and macOS have this problem?** Linux and macOS use `fork` by default to create child processes, which copy the parent process's memory space without re-executing the main module code. However, we still recommend using `if __name__ == "__main__"` entry point protection on all platforms. It's good programming practice and ensures cross-platform compatibility. --- ## ๐Ÿ“Š Version Comparison Overview | Aspect | Mainline 4.0.x | AFS 0.0.1-AFS | Mainline 4.2.0+ (planned) | AFS 1.0.0 (planned) | |--------|---------------|---------------|--------------------------|---------------------| | Opus support | โŒ | โœ… | โŒ | โœ… | | Playback formats | MP3/WAV/FLAC/OGG/AAC | +Opus | MP3/WAV/FLAC/OGG/AAC | +Opus + future formats | | Playback engine | SDL2 only | SDL2 + Opus native | SDL2 only | SDL2 + Opus native | | Opus error codes | โŒ | โœ… 2001-2010 | โŒ | โœ… 2001-2010 | | Auto DLL download | SDL2 | SDL2 + Opus DLLs | SDL2 | SDL2 + Opus DLLs | | AFS branch | โŒ | โœ… (AFS itself) | โŒ | โœ… (AFS itself) | | Test coverage | 421 tests | 650+ tests | 421 tests | 650+ tests | | Library size | ~2.5MB | ~3.87MB | ~2.5MB | ~2.8-3.5MB | | Version status | Stable | **Pre-release** | Planned | Planned (Sep 2026) | ### Version Relationship | Version | Type | Support Period | Use Case | |---------|------|---------------|----------| | v3.0.0 LTS | LTS | Until Mar 2031 | Production | | v4.0.x | LFV | ~6 months | Early adopters | | **AFS 0.0.1-AFS** | **Pre-release** | **~1 month** | **Opus testing & feedback** | | AFS 1.0.0+ (planned) | Stable | TBD | Opus permanent home (Sep 2026) | | Mainline 4.2.0+ | LFV | ~6 months | Returns to lightweight | ### Upgrade Recommendations | User Type | Recommendation | |-----------|---------------| | Production | Continue with v3.0.0 LTS, or wait for AFS 1.0.0 | | Dev/Test | Try AFS 0.0.1-AFS with Opus, help test & feedback | | Need Opus, willing to test | Use AFS 0.0.1-AFS, report bugs | | Need Opus, want long-term stability | Wait for AFS 1.0.0 (September 2026) | | No Opus needed, want lightweight | Wait for mainline 4.2.0+, or continue with 4.0.x | | Affected by v3.1.x metadata bug | Must upgrade to v4.0.0+ | --- ## ๐Ÿงช CI/CD Test Results โ€” Comprehensive Coverage, All Passed ### Opus Test Suite (OPUS_TEST.py) AFS 0.0.1-AFS includes a complete Opus test suite covering 16 test categories: | Category | Test Items | Description | |----------|-----------|-------------| | OP-1 | Module imports/constants/error codes | Verify all Opus modules, constants, error codes | | OP-2 | DLL loading & auto-download | Verify `_opusdll.py` loading, DLL existence, hash verification | | OP-3 | Metadata parsing | Verify Opus duration, sample rate, channels, bitrate, extended tags | | OP-4 | Playback functions | Verify `play_from_file`, `play_from_memory`, `new_aid` | | OP-5 | Playback control | Verify `pause_audio`, `play_audio`, `stop_audio` | | OP-6 | Volume control | Verify `set_volume` (0-128 boundary values) and `get_volume` | | OP-7 | Seek functionality | Verify `seek_audio` with various positions and boundary values | | OP-8 | Fade in/out | Verify `fadein_music`, `fadein_music_pos`, `fadeout_music` | | OP-9 | Opus vs native format distinction | Verify `_is_opus_file` and `AudioLibrary` auto-routing | | OP-10 | Batch parsing | Verify `batch_get_metadata`, `batch_get_duration`, `batch_by_type` | | OP-11 | Error code triggering | Confirm all 10 Opus error codes trigger correctly | | OP-12 | AID 1:1 mapping | Verify main AID โ†” Opus sub-AID full lifecycle | | OP-13 | Resource management | Verify `cleanup_function` releases resources correctly | | OP-14 | Boundary & error tests | Verify invalid parameter types, out-of-range values | | OP-15 | DLL-specific tests | Verify DLL file sizes, hashes, load idempotency | | OP-16 | Error code trigger specific tests | Verify each Opus error code trigger in real scenarios | **Test Results:** ``` ================================================================== Opus Test Summary ================================================================== Passed : 229 Failed : 0 Skipped: 0 ================================================================== ``` **All 229 tests passed, 0 failed, 0 skipped.** ### Comprehensive CICD Test Suite (CI,CD_TEST.py) ``` ================================================================== CICD Test Summary ================================================================== Passed : 650+ Failed : 0 Skipped: 0 ================================================================== ``` ### API Import Verification Test (IMPORT_TEST.py) ``` ============================================================ ๐Ÿ“Š FINAL SUMMARY ============================================================ ๐ŸŽ‰ ALL APIs EXIST! Documentation is accurate. ============================================================ โœ… Passed: 47 โŒ Failed: 0 ``` **All 47 API checks passed!** --- ## ๐Ÿ“– Technical Manual Update `show_tech_manual()` has been updated for AFS 0.0.1-AFS with: - **Section 2.1 OPUS SUPPORT** (New chapter) โ€” Opus format introduction, playback backend architecture, auto DLL download, OpusAudio class API reference, AID 1:1 mapping mechanism - **Section 10.4 Opus Error Codes** (New section) โ€” Complete 10 Opus error codes list (2001-2010), meanings and suggested actions - **Version History** โ€” AFS 0.0.1-AFS entry, Opus support, cross-platform playback backend, AFS branch establishment --- ## ๐ŸŒ apds.top Is Now Live! The ap_ds official project homepage is now live with TLS encryption! **๐ŸŽ‰ Visit: https://apds.top** **Website Features:** - ๐Ÿ“„ Full documentation: API reference, user guide, FAQ - ๐Ÿ“ฆ Version distribution: All version download links and changelogs - ๐Ÿ”— Repository navigation: GitCode (primary), Gitee (China mirror), GitHub (compatibility mirror) - โœ‰๏ธ Feedback system: Users can submit feedback directly through the website - ๐Ÿ”’ Full-site TLS encryption --- ## ๐Ÿ“ฆ Repository Strategy | Platform | Status | Purpose | |----------|--------|---------| | apds.top | โœ… Permanent home | Official source code, docs, downloads | | GitCode | โœ… Primary mirror | Global code hosting | | GitHub | โœ… Compatibility mirror | For GitHub developers (new!) | | Gitee | โœ… China mirror | Fast access for Chinese users | | GitLab (JiHu) | โŒ Deprecated | No longer maintained | --- ## โ„น๏ธ Overview **ap_ds AFS** is a lightweight (~3.87MB) Python audio library for playback and high-precision metadata parsing of MP3, FLAC, OGG, WAV, and **Opus** files. Zero external Python dependencies โ€” only uses the Python standard library with non-blocking playback suitable for GUI applications. **Core Features:** - ๐ŸŽต **Native Opus support** โ€” Dedicated playback pipeline independent of SDL2, cross-platform native audio output - ๐Ÿ“ฆ **Zero Python dependencies** โ€” Standard library only - ๐ŸŽฏ **High-precision metadata** โ€” WAV/FLAC 100%, OGG 99.99%, MP3 >98%, Opus 100% - โšก **Batch parsing** โ€” Parallel processing of hundreds of files using `batch_get_metadata()` - ๐Ÿ–ฅ๏ธ **Non-blocking playback** โ€” Ideal for GUI applications - ๐ŸŒ **Cross-platform** โ€” Windows, macOS, Linux, embedded ARM64 - ๐Ÿ“ **DAP recording system** โ€” Automatic playback history, metadata only - ๐Ÿงต **Python 3.15t support** โ€” No-GIL true parallelism, full multi-core performance - ๐Ÿ  **AFS permanent support** โ€” Permanent home for Opus and all future formats --- ## ๐Ÿ“ง Contact & Support ๐Ÿ“ง **License inquiries:** me@dvsyun.top or dvs6666@163.com โ€” 7 business days response ๐Ÿ› ๏ธ **Technical support:** apds.top ยท GitCode Issues ยท GitHub Issues ยท Gitee Issues ยท Email (completely free) **Author:** DVS (DvsXT) **Personal homepage & blog:** https://dvsx.top (under maintenance) **Author profile:** https://dvsyun.top/me/dvs **Email:** me@dvsyun.top ยท dvs6666@163.com **ap_ds Official Portal:** - ๐ŸŽต **Official website:** https://apds.top โ€” Permanent official homepage, full documentation, releases, license center - ๐Ÿ“ฆ **PyPI:** https://pypi.org/project/ap_ds/ - ๐ŸŒ **Mirror docs:** https://www.dvsyun.top/ap_ds