nextav/docs/active/media-streaming/TS_FILE_HANDLING_GUIDE.md

7.9 KiB

MPEG Transport Stream (.ts) File Handling Guide

Overview

MPEG Transport Stream (.ts) files are a common video container format that present unique opportunities for efficient web streaming. This guide explains the characteristics of .ts files and optimal handling strategies.

Understanding .ts Files

What are .ts files?

.ts files are MPEG Transport Stream containers that:

  1. Contain already-encoded video and audio streams - typically H.264 video and AAC audio
  2. Are designed for streaming and broadcast - specifically created for reliable transmission over networks
  3. Are the native format used by HLS (HTTP Live Streaming) - HLS breaks videos into .ts segments
  4. Can be "converted" instantly using container remuxing (no re-encoding needed)

Why .ts files from streaming sites work well

Downloaded .ts files from video streaming sites (like the ones you mentioned) are particularly suitable because:

  • They already contain web-compatible codecs (H.264/AAC)
  • They're optimized for streaming (proper keyframe intervals, constant bitrates)
  • They're single-segment streams (entire video in one .ts file)
  • They have proper metadata for duration and seeking

Technical Characteristics

Container vs. Codec

┌─────────────────┐    ┌──────────────────┐
│   .ts Container │    │  .mp4 Container  │
├─────────────────┤    ├──────────────────┤
│ H.264 Video ────┼────┼──► H.264 Video   │
│ AAC Audio   ────┼────┼──► AAC Audio     │
└─────────────────┘    └──────────────────┘
      Same codecs, different container

Browser Compatibility

Format Chrome Firefox Safari Edge Notes
.ts direct Browsers don't support .ts containers
.ts via HLS With hls.js library
.mp4 (converted) Native browser support

Implementation Strategies

Best for: Downloaded .ts files from streaming sites

// Current implementation in video-format-detector.ts
if (TS_STREAM_FORMATS.includes(extension)) {
  return createTSHLSFormat(video, extension);
}

Advantages:

  • Works with all browsers (via hls.js)
  • No conversion needed
  • Proper seeking and buffering
  • Leverages existing HLS infrastructure

How it works:

  1. Generate M3U8 playlist pointing to the .ts file as a single segment
  2. Serve the entire .ts file when segment 0 is requested
  3. Browser uses hls.js to handle the stream

Strategy 2: Container Conversion

Best for: Maximum browser compatibility

# Fast container remuxing (seconds, not minutes)
ffmpeg -i input.ts -c copy -movflags +faststart output.mp4

Advantages:

  • Native browser support (no JavaScript libraries needed)
  • Maximum compatibility
  • Optimized for web (faststart flag)
  • Very fast (container remuxing only)

API Usage:

// Convert .ts to .mp4
POST /api/videos/{id}/convert-ts
{
  "fastStart": true,
  "deleteOriginal": false
}

Strategy 3: Direct Streaming

Best for: External players

// Serve .ts file directly with proper MIME type
headers: {
  'Content-Type': 'video/mp2t',
  'Accept-Ranges': 'bytes'
}

Advantages:

  • No processing needed
  • Works with VLC, MPV, etc.
  • Full range request support

Current Implementation

Format Detection

// src/lib/video-format-detector.ts
const TS_STREAM_FORMATS = ['ts', 'm2ts', 'mts'];

if (TS_STREAM_FORMATS.includes(extension)) {
  return createTSHLSFormat(video, extension); // Default to HLS
}

HLS Playlist Generation

// src/app/api/stream/hls/[id]/playlist.m3u8/route.ts
function generateTSFilePlaylist(video: any, videoId: number): Response {
  const playlist = [
    '#EXTM3U',
    '#EXT-X-VERSION:3',
    `#EXT-X-TARGETDURATION:${Math.ceil(duration)}`,
    '#EXT-X-MEDIA-SEQUENCE:0',
    `#EXTINF:${duration.toFixed(3)},`,
    '../segment/0.ts',
    '#EXT-X-ENDLIST'
  ].join('\n');
}

Segment Serving

// src/app/api/stream/hls/[id]/segment/[segment]/route.ts
if (fileExtension === '.ts' && segmentIndex === 0) {
  // Serve entire .ts file as segment 0
  const file = fs.createReadStream(videoPath);
  return new Response(file, {
    headers: {
      'Content-Type': 'video/mp2t',
      'Accept-Ranges': 'bytes'
    }
  });
}

Testing and Validation

Test Suite

Run the comprehensive test suite:

node test-ts-streaming.mjs

Tests include:

  1. Format detection
  2. HLS playlist generation
  3. Segment serving
  4. Direct streaming
  5. External streaming
  6. Conversion status
  7. Media access information

Manual Testing

  1. Browser HLS Test:

    // In browser console with hls.js loaded
    const hls = new Hls();
    hls.loadSource('/api/stream/hls/109/playlist.m3u8');
    hls.attachMedia(video);
    
  2. VLC Direct Test:

    vlc http://localhost:3000/api/external-stream/109
    
  3. Container Conversion Test:

    curl -X POST http://localhost:3000/api/videos/109/convert-ts
    

Performance Comparison

Method Conversion Time Browser Support Quality Seeking
HLS Streaming 0s (instant) (with hls.js) Original
Container Conversion ~5-10s (native) Original
Direct Streaming 0s (instant) (browsers) Original (VLC)

Troubleshooting

Common Issues

  1. "Video cannot be played"

    • Check if hls.js is loaded
    • Verify M3U8 playlist is valid
    • Test segment URLs directly
  2. "Seeking not working"

    • Ensure Accept-Ranges header is set
    • Check if duration metadata is available
    • Verify keyframe intervals in source
  3. "Slow loading"

    • Check if faststart flag is used for MP4
    • Verify server supports range requests
    • Monitor network requests in dev tools

Debug Commands

# Check .ts file codec information
ffprobe -v quiet -print_format json -show_streams input.ts

# Verify HLS playlist
curl http://localhost:3000/api/stream/hls/109/playlist.m3u8

# Test segment serving
curl -I http://localhost:3000/api/stream/hls/109/segment/0.ts

Recommendations

For Downloaded .ts Files

  1. Primary: Use HLS streaming (current implementation)
  2. Fallback: Container conversion to .mp4
  3. External: Direct streaming for VLC/MPV

For Production

  1. Batch convert popular .ts files to .mp4 during off-peak hours
  2. Serve via CDN for better performance
  3. Monitor conversion success rates and user preferences
  4. Cache M3U8 playlists for better response times

Browser Integration

// Recommended ArtPlayer setup for .ts files
if (format.type === 'hls') {
  if (Hls.isSupported()) {
    const hls = new Hls({
      enableWorker: false,
      lowLatencyMode: false,
      backBufferLength: 90
    });
    hls.loadSource(format.url);
    hls.attachMedia(art.video);
  }
}

Conclusion

Your observation about VLC's instant "conversion" is spot-on - it's container remuxing, not re-encoding. The .ts files you have likely contain web-compatible H.264/AAC streams that just need the right serving strategy.

The optimal approach is:

  1. HLS streaming for immediate playback (already implemented)
  2. Container conversion for maximum compatibility (API available)
  3. Direct streaming for external players (already working)

This gives users the best of all worlds while leveraging the fact that .ts files from streaming sites are already optimized for web delivery.