VHF DSC decoder for Marine VHF radio. ITU-R M.493-13 compliant
4.4K
This container supersedes the old RTL-SDR-based dsc-decoder. It now operates as a file-based decoder — pass it WAV/MP3 audio recordings and it returns decoded DSC messages as JSON. No RTL-SDR, no privileged mode, no USB devices required.
Decode Marine VHF DSC (Digital Selective Calling) audio into JSON. 100% ITU-R M.493-13 compliant.
Pull and decode a file:
docker pull blackwellj/dsc-decoder:latest
# Decode a WAV file
docker run --rm -v /path/to/audio:/input:ro blackwellj/dsc-decoder /input/recording.wav --pretty
# Decode an MP3 file
docker run --rm -v /path/to/audio:/input:ro blackwellj/dsc-decoder /input/recording.mp3 --pretty
docker run -d --name dsc-decoder -p 8080:8080 blackwellj/dsc-decoder --serve --host 0.0.0.0 --port 8080
# Send audio via POST
curl -X POST "http://localhost:8080/decode?filename=audio.wav" \
--data-binary @recording.wav \
-H "Content-Type: application/octet-stream"
Returns JSON with decoded calls, or {"ok": false} if nothing found.
Files shorter than 0.3 seconds or longer than 5 seconds are rejected immediately to save CPU.
The decoder uses two paths and picks whichever works:
Activates automatically when Path 1 finds nothing. Gives ~10 dB more sensitivity:
{
"ok": true,
"calls": [
{
"format": {"symbol": 112, "name": "distress"},
"self_id": "002320011",
"ecc": {"received": 6, "calculated": 6, "ok": true},
"confidence": {"score": 240, "invalid_symbols": 0},
"message": {
"kind": "distress_call",
"nature": {"symbol": 7, "name": "undesignated distress"},
"position": {
"valid": true,
"latitude": 50.3333,
"longitude": -1.5
},
"utc": {"valid": true, "hour": 12, "minute": 30},
"subsequent_communication": {"symbol": 100, "name": "F3E/G3E all modes TP"}
}
}
]
}
| Format | Symbol | Description | Length |
|---|---|---|---|
| Distress | 112 | Emergency call with nature, position, UTC | 25 symbols |
| Individual | 120 | Point-to-point with address MMSI | 23 symbols |
| All ships | 116 | Broadcast to all vessels | Variable |
| Group | 114 | Call to a group of vessels | 23 symbols |
| Geographical area | 102 | Call to vessels in an area | Variable |
| Automatic service | 123 | Automated data exchange | Variable |
standard or symbol_level)| Feature | Status |
|---|---|
| ITU-R M.493-13 symbol encoding | ✅ Compliant |
| 10-bit DSC symbols (0–127) | ✅ Compliant |
| DX/RX time diversity | ✅ Compliant |
| RX-first phasing (14 symbols) | ✅ Compliant |
| ECC validation | ✅ Compliant |
| Distress call (25 symbols) | ✅ Compliant |
| Individual call (23 symbols) | ✅ Compliant |
| All ships call | ✅ Compliant |
| Position (all hemispheres) | ✅ Compliant |
| UTC time | ✅ Compliant |
| Distress nature codes (0–31) | ✅ Compliant |
| Telecommand tables (100–127) | ✅ Compliant |
| MP3 input (ffmpeg) | ✅ Supported |
| Symbol-level correlation (+10 dB) | ✅ Supported |
| Soft-decision Viterbi | ✅ Supported |
Tested against 1,000+ real off-air recordings from UK coastal VHF stations. The fixed decoder achieves approximately 13% decode rate on the full backlog (vs 0.1% from the original decoder). On stronger signals (within range of the receiving station), it decodes routinely.
https://github.com/blackwellj/coastalhub/tree/feat/tunnel-reliability-v2/apps/vhf-dsc-decoder
Content type
Image
Digest
sha256:95acd87d5…
Size
271 MB
Last updated
about 2 months ago
docker pull blackwellj/dsc-decoder