34 KiB
🎉 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_workerwas accidentally defined outside theOpusAudioclass, causingAttributeErroronfadeout/fadein/fadein_pos. It is now a proper class method. - Fade-in now stops and restarts —
fadein_musicpreviously 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_audiopreviously 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)andfadein_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 raisesValueError. A newOPUSFileparser delegates toopusplayer, soget_audio_duration,get_audio_metadataandbatch_get_metadataall support Opus files.- Directory scanning for
batch_get_metadatanow includes.opus.
Audio library routing (player.py)
get_audio_metadata_by_aid()now routes Opus AIDs to theOpusAudioengine, 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.pyfor 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
# 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:
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:
>>> 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
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)
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)
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
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)
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__":
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
# 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-devon 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.
# 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
waveOutOpento open default audio device - Uses
CreateEventW+WaitForSingleObjectfor buffer completion synchronization - 4 buffers rotating to eliminate stuttering
WAVEHDRstructure withc_void_pfor 64-bit compatibility
Linux (_play_worker_linux):
- Uses
snd_pcm_openwith "default" device - Uses
snd_pcm_set_paramsfor PCM parameters (S16_LE, interleaved mode) - Uses
snd_pcm_writeifor PCM data write - On
-EPIPE(buffer underrun), callssnd_pcm_recoverfor auto-recovery
macOS (_play_worker_macos):
- Uses
AudioQueueNewOutputto create output queue - Uses
AudioQueueAllocateBufferfor buffer allocation - Callback
HandleOutputBufferdecodes Opus and fillsmAudioData - Uses
AudioQueueStartto start,AudioQueueStopto 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:
- Checks if the 4 required DLLs exist in the package directory
- Downloads from
https://dvsyun.top/ap_ds/download/if missing or hash verification fails - Performs SHA256 hash verification after download
- 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
# 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):
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:
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):
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:
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