> ## 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.

# Timestamps, Clips, Streams

> Understand search results and generate playable video clips

Search returns structured results with timestamps, descriptions, and relevance scores. Generate playable clips or stream URLs from any result.

## Quick Example

<CodeGroup>
  ```python Python theme={null}
  results = video.search("car chase scene")

  # Access individual shots
  for shot in results.get_shots():
      print(f"{shot.start}s - {shot.end}s: {shot.text}")
      print(f"Score: {shot.search_score}")

  # Play all matching segments
  results.play()

  # Generate a stream URL
  stream_url = results.compile()
  print(stream_url)
  ```

  ```javascript Node.js theme={null}
  const results = await video.search("car chase scene");

  // Access individual shots
  for (const shot of results.shots) {
      console.log(`${shot.start}s - ${shot.end}s: ${shot.text}`);
      console.log(`Score: ${shot.searchScore}`);
  }

  // Get stream URL
  const streamUrl = await results.compile();
  console.log(streamUrl);
  ```
</CodeGroup>

***

## Search Result Structure

Each search returns a `SearchResult` object containing matching shots:

### Shot Attributes

| Attribute      | Type  | Description                       |
| :------------- | :---- | :-------------------------------- |
| `start`        | float | Start timestamp in seconds        |
| `end`          | float | End timestamp in seconds          |
| `text`         | str   | Content description or transcript |
| `search_score` | float | Relevance score (0-1)             |
| `stream_url`   | str   | Direct playback URL               |

### Accessing Results

<CodeGroup>
  ```python Python theme={null}
  results = video.search("introduction to the topic")

  # Get all shots
  shots = results.get_shots()

  # Access first result
  first_shot = shots[0]
  print(f"Starts at: {first_shot.start}")
  print(f"Ends at: {first_shot.end}")
  print(f"Content: {first_shot.text}")
  print(f"Relevance: {first_shot.search_score}")
  ```

  ```javascript Node.js theme={null}
  const results = await video.search("introduction to the topic");

  // Get all shots
  const shots = results.shots;

  // Access first result
  const firstShot = shots[0];
  console.log(`Starts at: ${firstShot.start}`);
  console.log(`Ends at: ${firstShot.end}`);
  console.log(`Content: ${firstShot.text}`);
  console.log(`Relevance: ${firstShot.searchScore}`);
  ```
</CodeGroup>

***

## Playback Options

### Play Results

<CodeGroup>
  ```python Python theme={null}
  results = video.search("product demo")
  results.play()  # Opens matching segments in your default browser
  ```

  ```javascript Node.js theme={null}
  const results = await video.search("product demo");
  const streamUrl = await results.compile();
  console.log(streamUrl); // Use this URL in a video player
  ```
</CodeGroup>

### Play Individual Shot

<CodeGroup>
  ```python Python theme={null}
  results = video.search("funny moments")
  shots = results.get_shots()

  # Play just the first match
  shots[0].play()
  ```

  ```javascript Node.js theme={null}
  const results = await video.search("funny moments");
  const shots = results.shots;

  // Play just the first match
  await shots[0].play();
  ```
</CodeGroup>

***

## Generate Stream URLs

Create playable URLs for embedding or sharing.

### From Search Results

<CodeGroup>
  ```python Python theme={null}
  results = video.search("highlight reel")
  stream_url = results.compile()
  # Returns: https://stream.videodb.io/v3/...
  ```

  ```javascript Node.js theme={null}
  const results = await video.search("highlight reel");
  const streamUrl = await results.compile();
  // Returns: https://stream.videodb.io/v3/...
  ```
</CodeGroup>

### From Custom Timestamps

<CodeGroup>
  ```python Python theme={null}
  # Generate stream from specific time ranges
  timestamps = [
      (10.5, 25.0),   # First segment
      (45.0, 60.0),   # Second segment
      (120.0, 135.5)  # Third segment
  ]

  stream_url = video.generate_stream(timestamps)
  ```

  ```javascript Node.js theme={null}
  // Generate stream from specific time ranges
  const timestamps = [
      [10.5, 25.0],   // First segment
      [45.0, 60.0],   // Second segment
      [120.0, 135.5]  // Third segment
  ];

  const streamUrl = await video.generateStream(timestamps);
  ```
</CodeGroup>

### Stream URL Format

Generated URLs are HLS streams that work in any video player:

```
https://stream.videodb.io/v3/published/manifests/{manifest-id}.m3u8
```

***

## Working with Timestamps

### Extract Timestamps from Results

<CodeGroup>
  ```python Python theme={null}
  results = video.search("key moments")

  # Get as list of tuples
  timestamps = [(shot.start, shot.end) for shot in results.get_shots()]
  # [(5.2, 15.0), (45.5, 52.3), (120.0, 145.8)]
  ```

  ```javascript Node.js theme={null}
  const results = await video.search("key moments");

  // Get as list of arrays
  const timestamps = results.shots.map(shot => [shot.start, shot.end]);
  // [[5.2, 15.0], [45.5, 52.3], [120.0, 145.8]]
  ```
</CodeGroup>

### Merge Overlapping Segments

<CodeGroup>
  ```python Python theme={null}
  def merge_timestamps(timestamps):
      """Merge overlapping time ranges"""
      if not timestamps:
          return []

      sorted_ts = sorted(timestamps)
      merged = [list(sorted_ts[0])]

      for start, end in sorted_ts[1:]:
          if start <= merged[-1][1]:
              merged[-1][1] = max(merged[-1][1], end)
          else:
              merged.append([start, end])

      return merged

  # Merge results from multiple searches
  ts1 = [(10, 20), (15, 25)]
  ts2 = [(22, 30), (50, 60)]
  merged = merge_timestamps(ts1 + ts2)
  # [[10, 30], [50, 60]]
  ```

  ```javascript Node.js theme={null}
  function mergeTimestamps(timestamps) {
      if (timestamps.length === 0) return [];

      const sorted = [...timestamps].sort((a, b) => a[0] - b[0]);
      const merged = [[...sorted[0]]];

      for (const [start, end] of sorted.slice(1)) {
          const last = merged[merged.length - 1];
          if (start <= last[1]) {
              last[1] = Math.max(last[1], end);
          } else {
              merged.push([start, end]);
          }
      }

      return merged;
  }

  // Merge results from multiple searches
  const ts1 = [[10, 20], [15, 25]];
  const ts2 = [[22, 30], [50, 60]];
  const merged = mergeTimestamps([...ts1, ...ts2]);
  // [[10, 30], [50, 60]]
  ```
</CodeGroup>

***

## Embedding Streams

### HTML Embed

```html theme={null}
<video controls>
  <source src="https://stream.videodb.io/v3/published/manifests/{id}.m3u8" type="application/x-mpegURL">
</video>
```

### React Component

```jsx theme={null}
import Hls from 'hls.js';

function VideoPlayer({ streamUrl }) {
  const videoRef = useRef(null);

  useEffect(() => {
    if (Hls.isSupported()) {
      const hls = new Hls();
      hls.loadSource(streamUrl);
      hls.attachMedia(videoRef.current);
    }
  }, [streamUrl]);

  return <video ref={videoRef} controls />;
}
```

### VideoDB Player

Use the built-in player with the console URL:

```
https://console.videodb.io/player?url={stream_url}
```

***

## Filter and Sort Results

### By Score

<CodeGroup>
  ```python Python theme={null}
  results = video.search("important moments")

  # Get high-confidence results only
  shots = results.get_shots()
  high_confidence = [s for s in shots if s.search_score > 0.5]
  ```

  ```javascript Node.js theme={null}
  const results = await video.search("important moments");

  // Get high-confidence results only
  const shots = results.shots;
  const highConfidence = shots.filter(s => s.searchScore > 0.5);
  ```
</CodeGroup>

### By Duration

<CodeGroup>
  ```python Python theme={null}
  results = video.search("long segments")

  # Get segments longer than 10 seconds
  shots = results.get_shots()
  long_segments = [s for s in shots if (s.end - s.start) > 10]
  ```

  ```javascript Node.js theme={null}
  const results = await video.search("long segments");

  // Get segments longer than 10 seconds
  const shots = results.shots;
  const longSegments = shots.filter(s => (s.end - s.start) > 10);
  ```
</CodeGroup>

***

## Next Steps

<CardGroup cols={2}>
  <Card icon="search" title="Collection Search" href="/pages/understand/search-and-retrieval/collection-search">
    Search across your entire library
  </Card>

  <Card icon="target" title="Accuracy Tips" href="/pages/understand/quality-and-evaluation/accuracy-tips">
    Improve search precision
  </Card>
</CardGroup>
