MMS Transcoding

June 12, 2026 · View on GitHub

This document covers the MMS media normalization pipeline in GOMSGGW.

Overview

GOMSGGW includes an intelligent transcoding system to ensure MMS messages are deliverable across all carrier networks and handset types. The system automatically processes media files to meet carrier-specific size and format requirements.

flowchart LR
    IN[Incoming MMS]
    DETECT[MIME Detection]
    DECIDE{Needs<br/>Transcoding?}
    TRANS[Transcode]
    PASS[Pass-through]
    OUT[Outgoing MMS]
    
    IN --> DETECT
    DETECT --> DECIDE
    DECIDE -->|Yes| TRANS
    DECIDE -->|No| PASS
    TRANS --> OUT
    PASS --> OUT

Carrier Size Limits

Different carriers impose different size limits for MMS:

TierMax SizeCarriers
Tier 11 MBSome Tier-1 carriers
Tier 2600 KBTelnyx, most carriers
Tier 3300 KBStrict carriers, international

GOMSGGW targets Tier 2 (600 KB) by default for maximum compatibility.


Supported Media Types

Images

Input FormatTranscodingOutput
JPEGResize/compress if neededJPEG
PNGConvert + compressJPEG
GIF (static)ConvertJPEG
GIF (animated)Pass-through or skipGIF
WebPConvertJPEG
HEICConvertJPEG

Processing Steps:

  1. Decode the image
  2. Resize if dimensions exceed target
  3. Re-encode as JPEG with quality adjustment
  4. Iterate quality until size target met

Video

Input FormatTranscodingOutput
MP4Transcode if neededMP4 (H.264)
MOVConvertMP4
AVIConvertMP4
WebMConvertMP4
3GPOptimize3GP

Processing Steps:

  1. Analyze input video properties
  2. Transcode using FFmpeg:
    • Video: H.264 baseline profile
    • Audio: AAC mono/stereo
    • Target bitrate for size compliance
  3. Fallback to 3GP format for maximum compatibility

Audio

Input FormatTranscodingOutput
MP3Pass-through or compressMP3
WAVConvertMP3
M4AConvertMP3
OGGConvertMP3
AMRPass-throughAMR

Transcoding Strategies

Adaptive Quality

The transcoder uses an iterative approach for images:

// Pseudocode
quality := 85
for quality >= 50 {
    encoded := encodeJPEG(image, quality)
    if len(encoded) <= targetSize {
        return encoded
    }
    quality -= 5
}
return errorTooLarge()

Dimension Limits

Maximum dimensions are enforced to reduce file sizes:

Media TypeMax WidthMax Height
Images1920 px1920 px
Videos1280 px720 px

FFmpeg Integration

Video and audio transcoding uses FFmpeg with optimized profiles:

# Video transcoding example
ffmpeg -i input.mov \
  -c:v libx264 -profile:v baseline -level 3.0 \
  -c:a aac -ac 2 -b:a 128k \
  -movflags +faststart \
  -maxrate 500k -bufsize 1M \
  output.mp4

Web Client Message Splitting

Web clients can control whether long messages are split into multiple SMS segments via ClientSettings:

{
  "disable_message_splitting": true
}

What disable_message_splitting Does

By default, messages longer than 160 characters (GSM-7) or 70 characters (UCS-2) are split into multiple SMS segments with UDH headers so the receiving handset can reassemble them.

When disable_message_splitting: true:

  • The full message body is delivered to the destination in a single payload (web→web only)
  • The original segment count is preserved in the message record
  • This only applies to web-to-web delivery; if the destination is a legacy (SMPP/MM4) client or a carrier, splitting still happens to comply with protocol limits

Note

This setting affects message segmentation, not media transcoding. MMS media is always processed through the transcoding pipeline described above.

When to Disable Splitting

Useful when the receiving web application prefers to handle a single long string rather than reassemble UDH-segmented parts. Most modern backends already reassemble automatically, so leaving splitting enabled (the default) is usually correct.


Error Handling

Transcoding Failures

When transcoding fails, the system:

  1. Logs the error with details
  2. Attempts fallback strategies:
    • Try lower quality settings
    • Try alternative format
    • Skip the problematic file
  3. Sends error notification to sender (if configured)

Size Limit Exceeded

If a file cannot be reduced to the target size:

{
  "error": "media_too_large",
  "message": "Image could not be reduced to carrier limits",
  "original_size": 5242880,
  "target_size": 614400,
  "filename": "large_photo.png"
}

Unsupported Format

For unrecognized media types:

{
  "error": "unsupported_media_type",
  "message": "Media type not supported for MMS",
  "content_type": "application/octet-stream",
  "filename": "document.exe"
}

Performance Considerations

CPU Usage

Video transcoding is CPU-intensive. Consider:

  • Limiting concurrent transcode operations
  • Using a dedicated transcoding worker pool
  • Horizontal scaling for high-volume deployments

Temporary Storage

The transcoder uses temporary files during processing:

  • Located in system temp directory
  • Automatically cleaned up after processing
  • Consider tmpfs for improved performance

Caching

Transcoded media can be cached by content hash:

  • Avoids re-processing identical files
  • Useful for repeated sends of same media
  • Configure cache size based on available storage

Monitoring

Metrics

The transcoding system exposes Prometheus metrics:

MetricTypeDescription
mms_transcode_totalCounterTotal transcode operations
mms_transcode_duration_secondsHistogramTranscode operation duration
mms_transcode_errors_totalCounterFailed transcode operations
mms_transcode_bytes_savedCounterBytes reduced by transcoding

Logging

Transcoding operations are logged at INFO level:

{
  "level": "info",
  "component": "transcoder",
  "event": "transcode_complete",
  "input_type": "image/png",
  "output_type": "image/jpeg",
  "input_size": 2048576,
  "output_size": 512000,
  "quality": 75,
  "duration_ms": 245
}

Configuration

Environment Variables

VariableDefaultDescription
MMS_MAX_SIZE614400Target size in bytes (600KB)
MMS_IMAGE_QUALITY85Initial JPEG quality
MMS_VIDEO_BITRATE500kTarget video bitrate
FFMPEG_PATH/usr/bin/ffmpegFFmpeg binary location
TRANSCODER_WORKERS4Concurrent transcode workers

Best Practices

For Legacy Clients

  • Always leave transcoding enabled
  • Trust the gateway to optimize for delivery

For Web Clients

  • Only disable transcoding if you manage media optimization
  • Consider the destination when disabling
  • Monitor for delivery failures

For High Volume

  • Scale horizontally for transcoding capacity
  • Consider dedicated transcoding workers
  • Implement media caching