# How FadCam Manages Video Segments and Auto-Splitting: Architecture Explained

> Discover how FadCam manages video segments and file splitting using Clip objects and a flexible splitAt method. Learn about its auto-splitting architecture for seamless recording.

- Repository: [Faded/FadCam](https://github.com/anonfaded/FadCam)
- Tags: architecture
- Published: 2026-05-13

---

**FadCam stores every editable video portion as a `Clip` object inside a `Timeline`, using a robust `splitAt()` method for manual editing and a size-monitoring `RecordingService` for automatic segment creation when file limits are reached.**

FadCam (anonfaded/FadCam) is an open-source Android camera application that handles long recordings through intelligent segment management. Understanding how it structures video segments and performs both manual and automatic splitting is essential for developers looking to implement similar timeline-based editing or automatic file rotation features. The architecture centers on two core classes—`Clip` and `Timeline`—working alongside recording services that monitor file size thresholds.

## Clip Representation: The Atomic Video Segment

Every visual element on FadCam’s editing timeline maps 1‑to‑1 to a **`Clip`** object defined in [`app/src/main/java/com/fadcam/ui/faditor/model/Clip.java`](https://github.com/anonfaded/FadCam/blob/main/app/src/main/java/com/fadcam/ui/faditor/model/Clip.java). This class encapsulates not just the media reference, but all transformation properties that persist when a segment is split.

```java
public class Clip {
    @NonNull private final String id;          // Unique identifier (UUID)
    @NonNull private final Uri sourceUri;      // Original video file path
    private long inPointMs;                     // Trim start in milliseconds
    private long outPointMs;                    // Trim end in milliseconds
    private long sourceDurationMs;              // Original untrimmed length
    private float speed = 1.0f;                 // Playback speed multiplier
    private float volume = 1.0f;                // Audio level (0.0 to 1.0)
    private int rotation = 0;                   // Rotation in degrees
    private boolean flipHorizontal = false;   // Mirror transform
    private RectF cropRect = new RectF(0, 0, 1, 1); // Normalized crop box
    
    // Clone constructor preserves all effects during splitting
    public Clip(@NonNull Clip other) {
        this.id = UUID.randomUUID().toString();
        this.sourceUri = other.sourceUri;
        this.inPointMs = other.inPointMs;
        this.outPointMs = other.outPointMs;
        this.sourceDurationMs = other.sourceDurationMs;
        this.speed = other.speed;
        this.volume = other.volume;
        this.rotation = other.rotation;
        this.flipHorizontal = other.flipHorizontal;
        this.cropRect = new RectF(other.cropRect);
    }
}

```

When FadCam converts a `Clip` for playback, it generates a Media3 `MediaItem` with a `ClippingConfiguration` set to the `inPointMs` and `outPointMs`. Because the clone constructor copies all effect parameters (`speed`, `volume`, `rotation`, etc.), splitting a clip automatically preserves the user’s creative adjustments across both resulting segments.

## Timeline: The Central Segment Manager

The **`Timeline`** class in [`app/src/main/java/com/fadcam/ui/faditor/model/Timeline.java`](https://github.com/anonfaded/FadCam/blob/main/app/src/main/java/com/fadcam/ui/faditor/model/Timeline.java) serves as the single source of truth for video composition. It maintains an ordered list of clips and provides the primary API for segment manipulation.

Key responsibilities of the Timeline include:

- **Ordered storage**: `private final List<Clip> clips` maintains chronological sequence
- **Duration calculation**: `getTotalDurationMs()` aggregates the duration of all clips, accounting for speed changes
- **Structural operations**: `addClip()`, `removeClip()`, `swapClips()`, and `moveClip()` handle reordering
- **Splitting logic**: `splitAt(int clipIndex, long splitPointMs)` executes the core segmentation algorithm

## Manual Splitting Logic via `splitAt()`

Manual splitting occurs when a user taps the split button in the editor. The `Timeline.splitAt()` method enforces a 100-millisecond minimum distance from clip edges to avoid creating micro-segments, then performs a non-destructive split by cloning the original clip and adjusting its boundary points.

```java
public int splitAt(int clipIndex, long splitPointMs) {
    // Validate index bounds
    if (clipIndex < 0 || clipIndex >= clips.size()) {
        return -1;
    }
    
    Clip original = clips.get(clipIndex);
    
    // Enforce minimum 100ms buffer from edges
    long minSplitMs = original.getInPointMs() + 100;
    long maxSplitMs = original.getOutPointMs() - 100;
    
    if (splitPointMs < minSplitMs || splitPointMs > maxSplitMs) {
        return -1; // Split point too close to edge
    }
    
    // Create two clips inheriting all effects from original
    Clip clipA = new Clip(original);
    clipA.setOutPointMs(splitPointMs);
    
    Clip clipB = new Clip(original);
    clipB.setInPointMs(splitPointMs);
    
    // Atomic replacement: remove original, insert A and B
    clips.remove(clipIndex);
    clips.add(clipIndex, clipB); // Add second part first (higher index)
    clips.add(clipIndex, clipA);  // Add first part at original index
    
    return clipIndex; // Return index of clipA (first part)
}

```

This approach ensures that metadata like speed adjustments or crop rectangles remain consistent across the split point, providing a seamless editing experience where segments behave as a continuous whole during playback.

## UI Integration in FaditorEditorActivity

The editor interface bridges user input and the Timeline API through [`FaditorEditorActivity.java`](https://github.com/anonfaded/FadCam/blob/main/FaditorEditorActivity.java). When the user positions the playhead and triggers a split, the activity calculates the absolute time position and invokes the Timeline method.

```java
private void splitAtPlayhead() {
    long currentPositionMs = player.getCurrentPosition();
    int selectedClipIndex = timelineView.getCurrentClipIndex();
    
    // Convert player position to clip-local time
    long clipStartTime = timeline.getClipStartTimeMs(selectedClipIndex);
    long absoluteSplitMs = currentPositionMs - clipStartTime;
    
    int newIndex = timeline.splitAt(selectedClipIndex, absoluteSplitMs);
    
    if (newIndex < 0) {
        Toast.makeText(this, R.string.faditor_split_error, Toast.LENGTH_SHORT).show();
    } else {
        Toast.makeText(this, R.string.faditor_split_success, Toast.LENGTH_SHORT).show();
        refreshTimelineView();
        updatePlayerClippingConfiguration();
    }
}

```

The UI enforces visual feedback through Toast messages defined in string resources, distinguishing between successful splits and validation errors (such as attempting to split within 100ms of a clip boundary).

## Auto-Splitting Implementation

FadCam’s auto-splitting feature automatically segments long recordings into multiple files when they approach a user-defined size limit (defaulting to 2GB, with options up to 4GB). This prevents filesystem limitations and ensures compatibility with older storage formats that impose file size caps.

### Configuration Layer

The feature is controlled via `value_video_split_enabled` in the settings layout [`app/src/main/res/layout/fragment_settings_video.xml`](https://github.com/anonfaded/FadCam/blob/main/app/src/main/res/layout/fragment_settings_video.xml). When enabled, the recording service receives the size threshold (in bytes) through shared preferences.

### RecordingService Logic

The automatic splitting logic resides in [`RecordingService.java`](https://github.com/anonfaded/FadCam/blob/main/RecordingService.java) within the `app/src/main/java/com/fadcam/service/` package. During active recording, the service monitors the output file size after each write cycle:

```java
private void monitorRecordingSize() {
    if (!videoSplittingEnabled) return;
    
    long maxBytes = splitSizeLimitBytes; // From user settings (2GB = 2_147_483_648L)
    File currentFile = recorder.getCurrentOutputFile();
    
    if (currentFile.length() >= maxBytes) {
        // Finalize current segment
        String finalizedPath = stopCurrentRecording();
        
        // Create new clip entry in Timeline for the completed segment
        Clip completedClip = new Clip(finalizedPath);
        timeline.addClip(completedClip);
        
        // Start fresh recording seamlessly
        startNewRecordingSegment();
        
        // The new recording automatically generates the next Clip on completion
    }
}

```

When the size threshold triggers, the service:
1. Finalizes the current MediaRecorder instance and closes the file
2. Creates a new `Clip` object referencing the completed file, adding it to the Timeline with `inPointMs` at 0 and `outPointMs` at the actual duration
3. Immediately initializes a new `MediaRecorder` targeting a fresh filename (typically timestamped or indexed)
4. Continues capture without user-visible interruption

This process creates a sequence of `Clip` entries that appear as continuous content in the editor, despite residing in separate physical files on disk.

## Interaction Between Manual and Automatic Splitting

Both splitting modalities converge on the same data model, ensuring architectural consistency:

- **Manual splits** (editor UI) use `Timeline.splitAt()` to subdivide existing clips during post-production
- **Auto-splits** (recording service) append new `Clip` instances to the Timeline when file size limits trigger during capture

Because both paths generate standard `Clip` objects with identical property inheritance, the export engine (`ExportService`) processes auto-split and manually-split segments through the same pipeline—applying transitions, mixing audio, and rendering effects without distinguishing the split origin.

## Summary

- **Clip Architecture**: Each segment is a `Clip` object in [`Clip.java`](https://github.com/anonfaded/FadCam/blob/main/Clip.java) storing trim points, effects, and source URI, with a copy constructor that preserves all properties during splits.
- **Timeline Management**: The `Timeline` class maintains an ordered `List<Clip>` and provides `splitAt()` with 100ms boundary validation to prevent micro-segments.
- **Manual Splitting**: [`FaditorEditorActivity.java`](https://github.com/anonfaded/FadCam/blob/main/FaditorEditorActivity.java) translates playhead positions into `splitAt()` calls, with immediate UI feedback via Toast messages.
- **Auto-Splitting**: [`RecordingService.java`](https://github.com/anonfaded/FadCam/blob/main/RecordingService.java) monitors file size against `value_video_split_enabled` preferences, automatically finalizing and restarting recordings at 2GB (or user-defined) thresholds while appending new clips to the Timeline.
- **Unified Model**: Both splitting methods produce identical `Clip` objects, allowing seamless editing and export regardless of whether segmentation occurred during recording or post-processing.

## Frequently Asked Questions

### How does FadCam preserve video effects when splitting a clip?

When `Timeline.splitAt()` executes, it invokes the `Clip` copy constructor (`new Clip(original)`) to create two new instances. This constructor duplicates all effect parameters—including `speed`, `volume`, `rotation`, `flipHorizontal`, and `cropRect`—so both resulting segments inherit the exact same visual and audio adjustments as the original.

### What is the minimum duration required between split points?

The `splitAt()` method enforces a **100-millisecond buffer** from both the `inPointMs` and `outPointMs` of the original clip. If the requested split point falls within 100ms of either edge, the method returns `-1` and the UI displays `R.string.faditor_split_error`, preventing the creation of unusable micro-segments.

### Where is the auto-split file size limit configured?

Users enable automatic splitting via **Settings → Video → "Enable Video Splitting"**, which controls the boolean preference `value_video_split_enabled`. The threshold size (default 2GB, maximum 4GB) is passed to [`RecordingService.java`](https://github.com/anonfaded/FadCam/blob/main/RecordingService.java), where the `monitorRecordingSize()` method compares `currentFile.length()` against this limit to trigger segment rotation.

### Can auto-split recordings be edited the same way as manually split videos?

Yes. Both manual and automatic splits produce identical `Clip` objects stored in the `Timeline`. Auto-split clips reference separate physical files but expose the same properties (`inPointMs`, `outPointMs`, effects) as manually split clips, allowing the `FaditorEditorActivity` to perform drag-and-drop reordering, trimming, and effect adjustments without distinguishing the split origin.