Files
tdarr-plugs/agent_notes/stream_organizer_refactor_plan.md
Tdarr Plugin Developer 24ab5118c0 Pre-refactor checkpoint: stream_organizer v4.8
Saving state before major refactoring of stream_organizer.js.
Current version is functional - this commit allows safe rollback.
2025-12-15 12:01:16 -08:00

3.3 KiB

Stream Organizer Refactoring Plan

Current State Analysis

File: Tdarr_Plugin_stream_organizer.js (v4.8) Total Lines: 777 Main Function Lines: ~500 (lines 251-772)

Problems Identified

  1. Monolithic Function: The plugin function handles too many responsibilities
  2. Deep Nesting: Multiple levels of conditionals and loops
  3. Difficult Testing: Cannot test sub-components in isolation
  4. Hard to Maintain: Changes require understanding entire 500-line function

Refactoring Strategy

Phase 1: Extract Stream Analysis Logic

New Functions:

  • analyzeStreams(file) → Returns categorized streams (video, audio, subtitle, other)
  • reorderStreamsByLanguage(streams, languageCodes, includeAudio, includeSubtitles) → Returns reordered streams
  • detectConversionNeeds(subtitleStreams, inputs) → Returns conversion analysis

Phase 2: Extract Subtitle Processing

New Functions:

  • processSubtitleExtraction(subtitleStreams, inputs, otherArguments, fs, path) → Returns extraction command + metadata
  • processCCExtraction(subtitleStreams, inputs, otherArguments, fs) → Returns CC extraction plan
  • buildSubtitleMapping(reorderedStreams, inputs, customEnglishCodes) → Returns subtitle map commands

Phase 3: Extract FFmpeg Command Building

New Functions:

  • buildFFmpegCommand(analysis, inputs) → Main orchestrator
  • buildBaseMapping(reorderedStreams, inputs) → Returns base -map commands
  • buildCodecArgs(includedSubtitles, inputs) → Returns codec arguments
  • buildDispositionArgs(audioIdx, subIdx) → Returns default flag arguments

Phase 4: Simplify Main Plugin Function

New Structure:

const plugin = (file, librarySettings, inputs, otherArguments) => {
  const { lib, fs, path } = initDependencies();
  const response = initResponse(file);
  
  try {
    inputs = validateAndSanitizeInputs(inputs, lib, details);
    
    const analysis = analyzeStreams(file, inputs, otherArguments, fs, path);
    
    if (!needsProcessing(analysis)) {
      return skipResponse(analysis.message);
    }
    
    const command = buildFFmpegCommand(analysis, inputs);
    
    return buildSuccessResponse(command, analysis, inputs);
  } catch (error) {
    return buildErrorResponse(error, file);
  }
};

Implementation Checklist

  • Create helper module structure at top of file
  • Extract analyzeStreams() family
  • Extract subtitle processing functions
  • Extract FFmpeg command builders
  • Refactor main plugin() function
  • Test equivalence (commands should be identical)
  • Update version to 4.9
  • Add inline documentation

Benefits

  1. Testability: Each function can be unit tested
  2. Readability: Functions have clear, single purposes
  3. Maintainability: Changes are localized to specific functions
  4. Debuggability: Stack traces show which component failed
  5. Reusability: Logic can be shared/adapted for other plugins

Risk Mitigation

  • No Behavior Changes: All existing logic preserved exactly
  • Incremental Approach: Refactor in phases, test after each
  • Version Bump: Clear signal this is a refactored version
  • Git History: Commit shows before/after for rollback

Next Steps

  1. Create backup/branch point
  2. Begin Phase 1: Stream analysis extraction
  3. Validate output equivalence with test files
  4. Continue with subsequent phases