> ## Documentation Index
> Fetch the complete documentation index at: https://docs.videodb.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Filters and Transitions

> Give individual clips a visual treatment and an independent entrance or exit transition in VideoDB Editor.

<a href="https://colab.research.google.com/github/video-db/videodb-cookbook/blob/main/editor/feature/filters_and_transitions.ipynb" target="_blank">
  <img src="https://colab.research.google.com/assets/colab-badge.svg" alt="Open In Colab" noZoom />
</a>

Filters change a clip's look. Transitions control how that clip enters or exits. Both belong on `Clip`, so the same source asset can appear more than once with different treatments. The focused snippets below assume `conn` and the source videos already exist. For the core parameters and other clip controls, see [Clip Parameters](/pages/act/programmable-editing/clip-parameters); for complete composition setup, see [Timeline Architecture](/pages/act/programmable-editing/timeline-architecture).

## Filters

Each clip can carry one visual treatment. The comparison below uses one source segment for every released filter and adds synchronized labels on a second track.

### Eight-filter showcase

The notebook places eight five-second clips on one track, each referencing the same source segment with one of the released filter values.

<CodeGroup>
  ```python Python theme={null}
  from videodb.editor import (
      Background, Clip, Filter, Font, TextAlignment, TextAsset,
      Timeline, Track, VideoAsset
  )

  timeline = Timeline(conn)
  timeline.background = "#2B2B2B"

  filters = [
      Filter.greyscale, Filter.blur, Filter.contrast, Filter.darken,
      Filter.lighten, Filter.boost, Filter.muted, Filter.negative,
  ]

  track = Track()
  for start, filter_value in enumerate(filters):
      track.add_clip(
          start * 5,
          Clip(
              asset=VideoAsset(id=video1.id, start=10),
              duration=5,
              filter=filter_value,
          ),
      )
  timeline.add_track(track)

  filter_names = [
      "Greyscale", "Blur", "Contrast", "Darken",
      "Lighten", "Boost", "Muted", "Negative",
  ]

  text_track = Track()
  for start, filter_name in enumerate(filter_names):
      text_asset = TextAsset(
          text=filter_name,
          font=Font(family="Clear Sans", size=36, color="#FFFFFF"),
          background=Background(
              color="#000000",
              opacity=0.6,
              height=60,
              width=200,
              text_alignment=TextAlignment.center,
          ),
      )
      text_track.add_clip(start * 5, Clip(asset=text_asset, duration=5))
  timeline.add_track(text_track)
  stream_url = timeline.generate_stream()
  ```

  ```javascript Node.js theme={null}
  import {
    Background, Clip, EditorTextAsset, EditorTimeline, EditorVideoAsset,
    Filter, Font, TextAlignment, Track
  } from "videodb";

  const timeline = new EditorTimeline(conn);
  timeline.background = "#2B2B2B";

  const filters = [
    Filter.greyscale, Filter.blur, Filter.contrast, Filter.darken,
    Filter.lighten, Filter.boost, Filter.muted, Filter.negative,
  ];

  const track = new Track();
  filters.forEach((filter, index) => {
    track.addClip(index * 5, new Clip({
      asset: new EditorVideoAsset({ id: video1.id, start: 10 }),
      duration: 5,
      filter,
    }));
  });
  timeline.addTrack(track);

  const filterNames = [
    "Greyscale", "Blur", "Contrast", "Darken",
    "Lighten", "Boost", "Muted", "Negative",
  ];

  const textTrack = new Track();
  filterNames.forEach((filterName, index) => {
    const textAsset = new EditorTextAsset({
      text: filterName,
      font: new Font({ family: "Clear Sans", size: 36, color: "#FFFFFF" }),
      background: new Background({
        color: "#000000",
        opacity: 0.6,
        height: 60,
        width: 200,
        textAlignment: TextAlignment.center,
      }),
    });
    textTrack.addClip(index * 5, new Clip({ asset: textAsset, duration: 5 }));
  });
  timeline.addTrack(textTrack);
  const streamUrl = await timeline.generateStream();
  ```
</CodeGroup>

<video controls width="100%">
  <source src="https://play.videodb.io/v1/863701c0-95c7-4b22-8e80-676a664af531.m3u8" type="application/x-mpegURL" />
</video>

## Transitions

Beyond the basic fade covered in [Clip Parameters](/pages/act/programmable-editing/clip-parameters), the notebook demonstrates motion-based transition names and mixed timings. Python uses `in_` because `in` is a keyword; Node uses `in` inside the configuration object.

### Reveal

`reveal` is the demonstrated motion-based alternative to a fade.

<CodeGroup>
  ```python Python theme={null}
  from videodb.editor import Clip, Timeline, Track, Transition, VideoAsset

  timeline = Timeline(conn)
  timeline.background = "#2B2B2B"

  clip = Clip(
      asset=VideoAsset(id=video1.id),
      duration=10,
      transition=Transition(in_="reveal", out="reveal", duration=2),
  )

  track = Track()
  track.add_clip(2, clip)
  timeline.add_track(track)
  stream_url = timeline.generate_stream()
  ```

  ```javascript Node.js theme={null}
  import { Clip, EditorTimeline, EditorVideoAsset, Track, Transition } from "videodb";

  const timeline = new EditorTimeline(conn);
  timeline.background = "#2B2B2B";

  const clip = new Clip({
    asset: new EditorVideoAsset({ id: video1.id }),
    duration: 10,
    transition: new Transition({ in: "reveal", out: "reveal", duration: 2 }),
  });

  const track = new Track();
  track.addClip(2, clip);
  timeline.addTrack(track);
  const streamUrl = await timeline.generateStream();
  ```
</CodeGroup>

<video controls width="100%">
  <source src="https://play.videodb.io/v1/29552263-c6c2-411a-88db-209e438bc4b7.m3u8" type="application/x-mpegURL" />
</video>

### Wipe and shuffle combinations

The notebook also demonstrates `wipe_left`, `wipe_right`, `shuffle_top_right`, `shuffle_bottom_right`, `shuffle_bottom_left`, and `shuffle_top_left`. These are demonstrated transition names, not a claim that they exhaust the server-side strings accepted by `Transition`.

<CodeGroup>
  ```python Python theme={null}
  from videodb.editor import Clip, Timeline, Track, Transition, VideoAsset

  timeline = Timeline(conn)
  timeline.background = "#2B2B2B"

  transition_names = [
      "wipe_left", "wipe_right", "shuffle_top_right",
      "shuffle_bottom_right", "shuffle_bottom_left", "shuffle_top_left",
  ]

  transition_track = Track()
  for start, name in enumerate(transition_names):
      transition_track.add_clip(
          start * 5,
          Clip(
              asset=VideoAsset(id=video1.id, start=10),
              duration=5,
              transition=Transition(in_=name, out=name, duration=1),
          ),
      )
  timeline.add_track(transition_track)
  stream_url = timeline.generate_stream()
  ```

  ```javascript Node.js theme={null}
  import { Clip, EditorTimeline, EditorVideoAsset, Track, Transition } from "videodb";

  const timeline = new EditorTimeline(conn);
  timeline.background = "#2B2B2B";

  const transitionNames = [
    "wipe_left", "wipe_right", "shuffle_top_right",
    "shuffle_bottom_right", "shuffle_bottom_left", "shuffle_top_left",
  ];

  const transitionTrack = new Track();
  transitionNames.forEach((name, index) => {
    transitionTrack.addClip(index * 5, new Clip({
      asset: new EditorVideoAsset({ id: video1.id, start: 10 }),
      duration: 5,
      transition: new Transition({ in: name, out: name, duration: 1 }),
    }));
  });
  timeline.addTrack(transitionTrack);
  const streamUrl = await timeline.generateStream();
  ```
</CodeGroup>

<video controls width="100%">
  <source src="https://play.videodb.io/v1/d769c6ce-861a-4fc4-b19b-b9f384590870.m3u8" type="application/x-mpegURL" />
</video>

## Combine filters and transitions

The properties are independent. This output uses three sequential clips with distinct filters and fade durations.

<CodeGroup>
  ```python Python theme={null}
  from videodb.editor import Clip, Filter, Timeline, Track, Transition, VideoAsset

  timeline = Timeline(conn)
  timeline.background = "#2B2B2B"

  showcase_track = Track()

  clips = [
      Clip(
          asset=VideoAsset(id=video1.id, start=5),
          duration=7,
          filter=Filter.greyscale,
          transition=Transition(in_="fade", out="fade", duration=2),
      ),
      Clip(
          asset=VideoAsset(id=video2.id, start=10),
          duration=7,
          filter=Filter.boost,
          transition=Transition(in_="fade", out="fade", duration=1),
      ),
      Clip(
          asset=VideoAsset(id=video1.id, start=30),
          duration=7,
          filter=Filter.negative,
          transition=Transition(in_="fade", out="fade", duration=2),
      ),
  ]

  for start, clip in zip([0, 7, 14], clips):
      showcase_track.add_clip(start, clip)
  timeline.add_track(showcase_track)
  stream_url = timeline.generate_stream()
  ```

  ```javascript Node.js theme={null}
  import { Clip, EditorTimeline, EditorVideoAsset, Filter, Track, Transition } from "videodb";

  const timeline = new EditorTimeline(conn);
  timeline.background = "#2B2B2B";

  const showcaseTrack = new Track();

  const clips = [
    new Clip({
      asset: new EditorVideoAsset({ id: video1.id, start: 5 }),
      duration: 7,
      filter: Filter.greyscale,
      transition: new Transition({ in: "fade", out: "fade", duration: 2 }),
    }),
    new Clip({
      asset: new EditorVideoAsset({ id: video2.id, start: 10 }),
      duration: 7,
      filter: Filter.boost,
      transition: new Transition({ in: "fade", out: "fade", duration: 1 }),
    }),
    new Clip({
      asset: new EditorVideoAsset({ id: video1.id, start: 30 }),
      duration: 7,
      filter: Filter.negative,
      transition: new Transition({ in: "fade", out: "fade", duration: 2 }),
    }),
  ];

  [0, 7, 14].forEach((start, index) => {
    showcaseTrack.addClip(start, clips[index]);
  });
  timeline.addTrack(showcaseTrack);
  const streamUrl = await timeline.generateStream();
  ```
</CodeGroup>

<video controls width="100%">
  <source src="https://play.videodb.io/v1/36f85c66-9756-4484-adcb-ecd3646bdafd.m3u8" type="application/x-mpegURL" />
</video>

For sequential placement and source trimming, continue with [Trimming Vs Timing](/pages/act/programmable-editing/trimming-vs-timing). For mixing effects with layout controls, return to [Clip Parameters](/pages/act/programmable-editing/clip-parameters).
