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

# Scene Operations

> Operations for managing scenes (videos).

Operations for managing scenes (videos).

Bases: `StashClientProtocol`

Mixin for scene-related client methods.

## Functions

### find\_scene

```python theme={null}
find_scene(id: str) -> Scene | None
```

Find a scene by its ID.

Parameters:

| Name | Type  | Description                 | Default    |
| ---- | ----- | --------------------------- | ---------- |
| `id` | `str` | The ID of the scene to find | *required* |

Returns:

| Type            | Description                           |
| --------------- | ------------------------------------- |
| `Scene \| None` | Scene object if found, None otherwise |

Raises:

| Type         | Description                  |
| ------------ | ---------------------------- |
| `ValueError` | If scene ID is None or empty |

Examples:

Find a scene and check its title:

```python theme={null}
scene = await client.find_scene("123")

if scene:
    print(f"Found scene: {scene.title}")
```

Access scene relationships:

```python theme={null}
scene = await client.find_scene("123")

if scene:
    # Get performer names
    performers = [p.name for p in scene.performers]
    # Get studio name
    studio_name = scene.studio.name if scene.studio else None
    # Get tag names
    tags = [t.name for t in scene.tags]
```

Check scene paths:

```python theme={null}
scene = await client.find_scene("123")

if scene:
    # Get streaming URL
    stream_url = scene.paths.stream
    # Get preview URL
    preview_url = scene.paths.preview
```

### find\_scenes

```python theme={null}
find_scenes(
    filter_: dict[str, Any] | None = None,
    scene_filter: dict[str, Any] | None = None,
    q: str | None = None,
) -> FindScenesResultType
```

Find scenes matching the given filters.

Parameters:

| Name           | Type                     | Description                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       | Default |
| -------------- | ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- |
| `filter_`      | `dict[str, Any] \| None` | Optional general filter parameters: - q: str (search query) - direction: SortDirectionEnum (ASC/DESC) - page: int - per\_page: int - sort: str (field to sort by)                                                                                                                                                                                                                                                                                                                                 | `None`  |
| `q`            | `str \| None`            | Optional search query (alternative to filter\_\["q"])                                                                                                                                                                                                                                                                                                                                                                                                                                             | `None`  |
| `scene_filter` | `dict[str, Any] \| None` | Optional scene-specific filter: - file\_count: IntCriterionInput - is\_missing: str (what data is missing) - organized: bool - path: StringCriterionInput - performer\_count: IntCriterionInput - performer\_tags: HierarchicalMultiCriterionInput - performers: MultiCriterionInput - rating100: IntCriterionInput - resolution: ResolutionEnum - studios: HierarchicalMultiCriterionInput - tag\_count: IntCriterionInput - tags: HierarchicalMultiCriterionInput - title: StringCriterionInput | `None`  |

Returns:

| Type                   | Description                                                                                                                                                                     |
| ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `FindScenesResultType` | FindScenesResultType containing: - count: Total number of matching scenes - duration: Total duration in seconds - filesize: Total size in bytes - scenes: List of Scene objects |

Examples:

Find all organized scenes:

```python theme={null}
result = await client.find_scenes(
    scene_filter={"organized": True}
)
print(f"Found {result.count} organized scenes")
for scene in result.scenes:
    print(f"- {scene.title}")
```

Find scenes with specific performers:

```python theme={null}
result = await client.find_scenes(
    scene_filter={
        "performers": {
            "value": ["performer1", "performer2"],
            "modifier": "INCLUDES_ALL"
        }
    }
)
```

Find scenes with high rating and sort by date:

```python theme={null}
result = await client.find_scenes(
    filter_={
        "direction": "DESC",
        "sort": "date",
    },
    scene_filter={
        "rating100": {
            "value": 80,
            "modifier": "GREATER_THAN"
        }
    }
)
```

Paginate results:

```python theme={null}
result = await client.find_scenes(
    filter_={
        "page": 1,
        "per_page": 25,
    }
)
```

### create\_scene

```python theme={null}
create_scene(scene: Scene) -> Scene
```

Create a new scene in Stash.

Parameters:

<table>
  <colgroup>
    <col style="width: 25%" />

    <col style="width: 25%" />

    <col style="width: 25%" />

    <col style="width: 25%" />
  </colgroup>

  <thead>
    <tr>
      <th>Name</th>
      <th>Type</th>
      <th>Description</th>
      <th>Default</th>
    </tr>
  </thead>

  <tbody>
    <tr>
      <td><code>scene</code></td>
      <td><code>Scene</code></td>
      <td><p>Scene object with the data to create. Required fields: - title: Scene title - urls: List of URLs associated with the scene - organized: Whether the scene is organized</p>
      <p>Note: created\_at and updated\_at are handled by Stash</p></td>
      <td><em>required</em></td>
    </tr>
  </tbody>
</table>

Returns:

| Type    | Description                                                  |
| ------- | ------------------------------------------------------------ |
| `Scene` | Created Scene object with ID and any server-generated fields |

Raises:

| Type             | Description                  |
| ---------------- | ---------------------------- |
| `ValueError`     | If the scene data is invalid |
| `TransportError` | If the request fails         |

Examples:

Create a basic scene:

```python theme={null}
scene = Scene(
    title="My Scene",
    urls=["https://example.com/scene"],
    organized=True,  # created_at and updated_at handled by Stash
)
created = await client.create_scene(scene)
print(f"Created scene with ID: {created.id}")
```

Create scene with relationships:

```python theme={null}
scene = Scene(
    title="My Scene",
    urls=["https://example.com/scene"],
    organized=True,  # created_at and updated_at handled by Stash
    # Add relationships
    performers=[performer1, performer2],
    studio=studio,
    tags=[tag1, tag2],
)
created = await client.create_scene(scene)
```

Create scene with metadata:

```python theme={null}
scene = Scene(
    title="My Scene",
    urls=["https://example.com/scene"],
    organized=True,  # created_at and updated_at handled by Stash
    # Add metadata
    details="Scene description",
    date="2024-01-31",
    rating100=85,
    code="SCENE123",
)
created = await client.create_scene(scene)
```

### update\_scene

```python theme={null}
update_scene(scene: Scene) -> Scene
```

Update an existing scene in Stash.

Parameters:

| Name    | Type    | Description                                                                                                                                                    | Default    |
| ------- | ------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- |
| `scene` | `Scene` | Scene object with updated data. Required fields: - id: Scene ID to update Any other fields that are set will be updated. Fields that are None will be ignored. | *required* |

Returns:

| Type    | Description                                           |
| ------- | ----------------------------------------------------- |
| `Scene` | Updated Scene object with any server-generated fields |

Raises:

| Type             | Description                  |
| ---------------- | ---------------------------- |
| `ValueError`     | If the scene data is invalid |
| `TransportError` | If the request fails         |

Examples:

Update scene title and rating:

```python theme={null}
scene = await client.find_scene("123")
if scene:
    scene.title = "New Title"
    scene.rating100 = 90
    updated = await client.update_scene(scene)
    print(f"Updated scene: {updated.title}")
```

Update scene relationships:

```python theme={null}
scene = await client.find_scene("123")
if scene:
    # Add new performers
    scene.performers.extend([new_performer1, new_performer2])
    # Set new studio
    scene.studio = new_studio
    # Add new tags
    scene.tags.extend([new_tag1, new_tag2])
    updated = await client.update_scene(scene)
```

Update scene metadata:

```python theme={null}
scene = await client.find_scene("123")
if scene:
    # Update metadata
    scene.details = "New description"
    scene.date = "2024-01-31"
    scene.code = "NEWCODE123"
    scene.organized = True
    updated = await client.update_scene(scene)
```

Update scene URLs:

```python theme={null}
scene = await client.find_scene("123")
if scene:
    # Replace URLs
    scene.urls = [
        "https://example.com/new-url",
    ]
    updated = await client.update_scene(scene)
```

Remove scene relationships:

```python theme={null}
scene = await client.find_scene("123")
if scene:
    # Clear studio
    scene.studio = None
    # Clear performers
    scene.performers = []
    updated = await client.update_scene(scene)
```

### find\_duplicate\_scenes

```python theme={null}
find_duplicate_scenes(
    distance: int | None = None,
    duration_diff: float | None = None,
) -> list[list[Scene]]
```

Find groups of scenes that are perceptual duplicates.

Parameters:

| Name            | Type            | Description                                                       | Default |
| --------------- | --------------- | ----------------------------------------------------------------- | ------- |
| `distance`      | `int \| None`   | Maximum phash distance between scenes to be considered duplicates | `None`  |
| `duration_diff` | `float \| None` | Maximum difference in seconds between scene durations             | `None`  |

Returns:

| Type                | Description                                                          |
| ------------------- | -------------------------------------------------------------------- |
| `list[list[Scene]]` | List of scene groups, where each group is a list of duplicate scenes |

### parse\_scene\_filenames

```python theme={null}
parse_scene_filenames(
    filter_: dict[str, Any] | None = None,
    config: dict[str, Any] | None = None,
) -> dict[str, Any]
```

Parse scene filenames using the given configuration.

Parameters:

| Name      | Type                     | Description                                                                                      | Default |
| --------- | ------------------------ | ------------------------------------------------------------------------------------------------ | ------- |
| `filter_` | `dict[str, Any] \| None` | Optional filter to select scenes                                                                 | `None`  |
| `config`  | `dict[str, Any] \| None` | Parser configuration: - whitespace\_separator: bool - field\_separator: str - fields: list\[str] | `None`  |

Returns:

| Type             | Description                         |
| ---------------- | ----------------------------------- |
| `dict[str, Any]` | Dictionary containing parse results |

### scene\_wall

```python theme={null}
scene_wall(q: str | None = None) -> list[Scene]
```

Get random scenes for the wall.

Parameters:

| Name | Type          | Description           | Default |
| ---- | ------------- | --------------------- | ------- |
| `q`  | `str \| None` | Optional search query | `None`  |

Returns:

| Type          | Description                  |
| ------------- | ---------------------------- |
| `list[Scene]` | List of random Scene objects |

### bulk\_scene\_update

```python theme={null}
bulk_scene_update(
    input_data: dict[str, Any],
) -> list[Scene]
```

```python theme={null}
bulk_scene_update(
    input_data: dict[str, Any], *, return_fields: str
) -> list[dict[str, Any]]
```

```python theme={null}
bulk_scene_update(
    input_data: dict[str, Any],
    *,
    return_fields: str | None = None,
) -> list[Scene] | list[dict[str, Any]]
```

Update multiple scenes at once.

Parameters:

| Name            | Type             | Description                                                                                                                        | Default    |
| --------------- | ---------------- | ---------------------------------------------------------------------------------------------------------------------------------- | ---------- |
| `input_data`    | `dict[str, Any]` | Dictionary containing: - ids: List of scene IDs to update - Any other fields to update on all scenes                               | *required* |
| `return_fields` | `str \| None`    | If provided, use a minimal inline mutation requesting only these fields (e.g. `"id"`). Returns raw dicts instead of Scene objects. | `None`     |

Returns:

| Type                                  | Description                                                    |
| ------------------------------------- | -------------------------------------------------------------- |
| `list[Scene] \| list[dict[str, Any]]` | List of updated Scene objects (default), or list of dicts when |
| `list[Scene] \| list[dict[str, Any]]` | `return_fields` is provided.                                   |

### scenes\_update

```python theme={null}
scenes_update(scenes: list[Scene]) -> list[Scene]
```

Update multiple scenes with individual data.

Parameters:

| Name     | Type          | Description                                           | Default    |
| -------- | ------------- | ----------------------------------------------------- | ---------- |
| `scenes` | `list[Scene]` | List of Scene objects to update, each must have an ID | *required* |

Returns:

| Type          | Description                   |
| ------------- | ----------------------------- |
| `list[Scene]` | List of updated Scene objects |

### scene\_generate\_screenshot

```python theme={null}
scene_generate_screenshot(
    id: str, at: float | None = None
) -> str
```

Generate a screenshot for a scene.

Parameters:

| Name | Type            | Description                                    | Default    |
| ---- | --------------- | ---------------------------------------------- | ---------- |
| `id` | `str`           | Scene ID                                       | *required* |
| `at` | `float \| None` | Optional time in seconds to take screenshot at | `None`     |

Returns:

| Type  | Description                      |
| ----- | -------------------------------- |
| `str` | Path to the generated screenshot |

Raises:

| Type             | Description               |
| ---------------- | ------------------------- |
| `ValueError`     | If the scene is not found |
| `TransportError` | If the request fails      |

### find\_scene\_by\_hash

```python theme={null}
find_scene_by_hash(
    input_data: SceneHashInput | dict[str, Any],
) -> Scene | None
```

Find a scene by its hash (checksum or oshash).

Parameters:

| Name         | Type                               | Description                                                                                   | Default    |
| ------------ | ---------------------------------- | --------------------------------------------------------------------------------------------- | ---------- |
| `input_data` | `SceneHashInput \| dict[str, Any]` | SceneHashInput object or dictionary. At least one hash (checksum or oshash) must be provided. | *required* |

Returns:

| Type            | Description                           |
| --------------- | ------------------------------------- |
| `Scene \| None` | Scene object if found, None otherwise |

Examples:

Find scene by MD5 checksum:

```python theme={null}
scene = await client.find_scene_by_hash({
    "checksum": "abc123def456..."
})
if scene:
    print(f"Found scene: {scene.title}")
```

Find scene by OSHash:

```python theme={null}
scene = await client.find_scene_by_hash({
    "oshash": "xyz789..."
})
```

Using the input type:

```python theme={null}
from ...types import SceneHashInput

input_data = SceneHashInput(checksum="abc123")
scene = await client.find_scene_by_hash(input_data)
```

### scene\_destroy

```python theme={null}
scene_destroy(
    input_data: SceneDestroyInput | dict[str, Any],
) -> bool
```

Delete a scene.

Parameters:

| Name         | Type                                  | Description                             | Default    |
| ------------ | ------------------------------------- | --------------------------------------- | ---------- |
| `input_data` | `SceneDestroyInput \| dict[str, Any]` | SceneDestroyInput object or dictionary. | *required* |

Returns:

| Type   | Description                                |
| ------ | ------------------------------------------ |
| `bool` | True if the scene was successfully deleted |

Raises:

| Type             | Description                |
| ---------------- | -------------------------- |
| `ValueError`     | If the scene ID is invalid |
| `TransportError` | If the request fails       |

Examples:

Delete a scene without deleting the file:

```python theme={null}
result = await client.scene_destroy({
    "id": "123",
    "delete_file": False,
    "delete_generated": True
})
print(f"Scene deleted: {result}")
```

Delete a scene and its file:

```python theme={null}
result = await client.scene_destroy({
    "id": "123",
    "delete_file": True,
    "delete_generated": True
})
```

Using the input type:

```python theme={null}
from ...types import SceneDestroyInput

input_data = SceneDestroyInput(
    id="123",
    delete_file=True,
    delete_generated=True
)
result = await client.scene_destroy(input_data)
```

### scenes\_destroy

```python theme={null}
scenes_destroy(
    input_data: ScenesDestroyInput | dict[str, Any],
) -> bool
```

Delete multiple scenes.

Parameters:

| Name         | Type                                   | Description                              | Default    |
| ------------ | -------------------------------------- | ---------------------------------------- | ---------- |
| `input_data` | `ScenesDestroyInput \| dict[str, Any]` | ScenesDestroyInput object or dictionary. | *required* |

Returns:

| Type   | Description                                  |
| ------ | -------------------------------------------- |
| `bool` | True if the scenes were successfully deleted |

Raises:

| Type             | Description                |
| ---------------- | -------------------------- |
| `ValueError`     | If any scene ID is invalid |
| `TransportError` | If the request fails       |

Examples:

Delete multiple scenes without deleting files:

```python theme={null}
result = await client.scenes_destroy({
    "ids": ["123", "456", "789"],
    "delete_file": False,
    "delete_generated": True
})
print(f"Scenes deleted: {result}")
```

Delete multiple scenes and their files:

```python theme={null}
result = await client.scenes_destroy({
    "ids": ["123", "456"],
    "delete_file": True,
    "delete_generated": True
})
```

Using the input type:

```python theme={null}
from ...types import ScenesDestroyInput

input_data = ScenesDestroyInput(
    ids=["123", "456", "789"],
    delete_file=False,
    delete_generated=True
)
result = await client.scenes_destroy(input_data)
```

### scene\_merge

```python theme={null}
scene_merge(
    input_data: SceneMergeInput | dict[str, Any],
) -> Scene
```

Merge multiple scenes into one destination scene.

Parameters:

| Name         | Type                                | Description                           | Default    |
| ------------ | ----------------------------------- | ------------------------------------- | ---------- |
| `input_data` | `SceneMergeInput \| dict[str, Any]` | SceneMergeInput object or dictionary. | *required* |

Returns:

| Type    | Description                      |
| ------- | -------------------------------- |
| `Scene` | Updated destination Scene object |

Raises:

| Type             | Description                  |
| ---------------- | ---------------------------- |
| `ValueError`     | If the input data is invalid |
| `TransportError` | If the request fails         |

Examples:

Merge two scenes into one:

```python theme={null}
merged = await client.scene_merge({
    "source": ["123", "456"],
    "destination": "789"
})
print(f"Merged into scene: {merged.title}")
```

Merge scenes and update metadata:

```python theme={null}
from stash_graphql_client.types import SceneMergeInput

input_data = SceneMergeInput(
    source=["123", "456"],
    destination="789",
    values={"title": "Merged Scene"},
    play_history=True,
    o_history=True
)
merged = await client.scene_merge(input_data)
```

### scene\_add\_o

```python theme={null}
scene_add_o(
    id: str, times: list[Timestamp] | None = None
) -> HistoryMutationResult
```

Add O-count entry for a scene.

Parameters:

| Name    | Type                      | Description                                                      | Default    |
| ------- | ------------------------- | ---------------------------------------------------------------- | ---------- |
| `id`    | `str`                     | Scene ID                                                         | *required* |
| `times` | `list[Timestamp] \| None` | Optional list of timestamps. If not provided, uses current time. | `None`     |

Returns:

| Type                    | Description                                                                                      |
| ----------------------- | ------------------------------------------------------------------------------------------------ |
| `HistoryMutationResult` | HistoryMutationResult containing: - count: New O-count value - history: List of all O timestamps |

Examples:

Add O-count with current time:

```python theme={null}
result = await client.scene_add_o("123")
print(f"New O-count: {result.count}")
```

Add O-count with specific times:

```python theme={null}
result = await client.scene_add_o(
    "123",
    times=["2024-01-15T10:30:00Z", "2024-01-16T14:20:00Z"]
)
```

### scene\_delete\_o

```python theme={null}
scene_delete_o(
    id: str, times: list[Timestamp] | None = None
) -> HistoryMutationResult
```

Delete O-count entry from a scene.

Parameters:

| Name    | Type                      | Description                                                                 | Default    |
| ------- | ------------------------- | --------------------------------------------------------------------------- | ---------- |
| `id`    | `str`                     | Scene ID                                                                    | *required* |
| `times` | `list[Timestamp] \| None` | Optional list of timestamps to remove. If not provided, removes last entry. | `None`     |

Returns:

| Type                    | Description                                                                                            |
| ----------------------- | ------------------------------------------------------------------------------------------------------ |
| `HistoryMutationResult` | HistoryMutationResult containing: - count: New O-count value - history: List of remaining O timestamps |

Examples:

Remove last O-count entry:

```python theme={null}
result = await client.scene_delete_o("123")
print(f"New O-count: {result.count}")
```

Remove specific timestamp:

```python theme={null}
result = await client.scene_delete_o(
    "123",
    times=["2024-01-15T10:30:00Z"]
)
```

### scene\_reset\_o

```python theme={null}
scene_reset_o(id: str) -> int
```

Reset scene O-count to 0.

Parameters:

| Name | Type  | Description | Default    |
| ---- | ----- | ----------- | ---------- |
| `id` | `str` | Scene ID    | *required* |

Returns:

| Type  | Description           |
| ----- | --------------------- |
| `int` | New O-count value (0) |

<Note>
  **Example**

  ```python theme={null}
  count = await client.scene_reset_o("123")
  print(f"O-count reset to: {count}")
  ```
</Note>

### scene\_save\_activity

```python theme={null}
scene_save_activity(
    id: str,
    resume_time: float | None = None,
    play_duration: float | None = None,
) -> bool
```

Save scene playback activity.

Parameters:

| Name            | Type            | Description                  | Default    |
| --------------- | --------------- | ---------------------------- | ---------- |
| `id`            | `str`           | Scene ID                     | *required* |
| `resume_time`   | `float \| None` | Resume time point in seconds | `None`     |
| `play_duration` | `float \| None` | Duration played in seconds   | `None`     |

Returns:

| Type   | Description                             |
| ------ | --------------------------------------- |
| `bool` | True if activity was saved successfully |

Examples:

Save resume point:

```python theme={null}
await client.scene_save_activity("123", resume_time=120.5)
```

Save play duration:

```python theme={null}
await client.scene_save_activity("123", play_duration=300.0)
```

Save both:

```python theme={null}
await client.scene_save_activity(
    "123",
    resume_time=120.5,
    play_duration=300.0
)
```

### scene\_reset\_activity

```python theme={null}
scene_reset_activity(
    id: str,
    reset_resume: bool = False,
    reset_duration: bool = False,
) -> bool
```

Reset scene activity tracking.

Parameters:

| Name             | Type   | Description                        | Default    |
| ---------------- | ------ | ---------------------------------- | ---------- |
| `id`             | `str`  | Scene ID                           | *required* |
| `reset_resume`   | `bool` | Whether to reset resume time point | `False`    |
| `reset_duration` | `bool` | Whether to reset play duration     | `False`    |

Returns:

| Type   | Description                             |
| ------ | --------------------------------------- |
| `bool` | True if activity was reset successfully |

Examples:

Reset resume point:

```python theme={null}
await client.scene_reset_activity("123", reset_resume=True)
```

Reset play duration:

```python theme={null}
await client.scene_reset_activity("123", reset_duration=True)
```

Reset both:

```python theme={null}
await client.scene_reset_activity(
    "123",
    reset_resume=True,
    reset_duration=True
)
```

### scene\_add\_play

```python theme={null}
scene_add_play(
    id: str, times: list[Timestamp] | None = None
) -> HistoryMutationResult
```

Add play count entry for a scene.

Parameters:

| Name    | Type                      | Description                                                      | Default    |
| ------- | ------------------------- | ---------------------------------------------------------------- | ---------- |
| `id`    | `str`                     | Scene ID                                                         | *required* |
| `times` | `list[Timestamp] \| None` | Optional list of timestamps. If not provided, uses current time. | `None`     |

Returns:

| Type                    | Description                                                                                            |
| ----------------------- | ------------------------------------------------------------------------------------------------------ |
| `HistoryMutationResult` | HistoryMutationResult containing: - count: New play count value - history: List of all play timestamps |

Examples:

Add play with current time:

```python theme={null}
result = await client.scene_add_play("123")
print(f"New play count: {result.count}")
```

Add play with specific times:

```python theme={null}
result = await client.scene_add_play(
    "123",
    times=["2024-01-15T10:30:00Z"]
)
```

### scene\_delete\_play

```python theme={null}
scene_delete_play(
    id: str, times: list[Timestamp] | None = None
) -> HistoryMutationResult
```

Delete play count entry from a scene.

Parameters:

| Name    | Type                      | Description                                                                 | Default    |
| ------- | ------------------------- | --------------------------------------------------------------------------- | ---------- |
| `id`    | `str`                     | Scene ID                                                                    | *required* |
| `times` | `list[Timestamp] \| None` | Optional list of timestamps to remove. If not provided, removes last entry. | `None`     |

Returns:

| Type                    | Description                                                                                                  |
| ----------------------- | ------------------------------------------------------------------------------------------------------------ |
| `HistoryMutationResult` | HistoryMutationResult containing: - count: New play count value - history: List of remaining play timestamps |

Examples:

Remove last play entry:

```python theme={null}
result = await client.scene_delete_play("123")
print(f"New play count: {result.count}")
```

Remove specific timestamp:

```python theme={null}
result = await client.scene_delete_play(
    "123",
    times=["2024-01-15T10:30:00Z"]
)
```

### scene\_reset\_play\_count

```python theme={null}
scene_reset_play_count(id: str) -> int
```

Reset scene play count to 0.

Parameters:

| Name | Type  | Description | Default    |
| ---- | ----- | ----------- | ---------- |
| `id` | `str` | Scene ID    | *required* |

Returns:

| Type  | Description              |
| ----- | ------------------------ |
| `int` | New play count value (0) |

<Note>
  **Example**

  ```python theme={null}
  count = await client.scene_reset_play_count("123")
  print(f"Play count reset to: {count}")
  ```
</Note>

### find\_scenes\_by\_path\_regex

```python theme={null}
find_scenes_by_path_regex(
    filter_: dict[str, Any] | None = None,
) -> FindScenesResultType
```

Find scenes by path regex pattern.

Parameters:

| Name      | Type                     | Description       | Default |
| --------- | ------------------------ | ----------------- | ------- |
| `filter_` | `dict[str, Any] \| None` | Filter parameters | `None`  |

Returns:

| Type                   | Description                                                                                                                                                                                            |
| ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `FindScenesResultType` | FindScenesResultType containing: - count: Total number of matches - duration: Total duration in seconds - filesize: Total file size in bytes - scenes: List of Scene objects matching the path pattern |

### scene\_streams

```python theme={null}
scene_streams(scene_id: str) -> list[SceneStreamEndpoint]
```

Get streaming endpoints for a scene.

Parameters:

| Name       | Type  | Description         | Default    |
| ---------- | ----- | ------------------- | ---------- |
| `scene_id` | `str` | The ID of the scene | *required* |

Returns:

| Type                        | Description                                                                                                                                          |
| --------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
| `list[SceneStreamEndpoint]` | List of SceneStreamEndpoint objects containing: - url: Stream URL - mime\_type: MIME type of the stream - label: Label for the stream quality/format |

Examples:

Get streaming endpoints:

```python theme={null}
streams = await client.scene_streams("123")
for stream in streams:
    print(f"{stream.label}: {stream.url} ({stream.mime_type})")
```

Access specific stream properties:

```python theme={null}
streams = await client.scene_streams("123")
if streams:
    primary_stream = streams[0]
    print(f"Primary stream URL: {primary_stream.url}")
```

### merge\_scene\_markers

```python theme={null}
merge_scene_markers(
    target_scene_id: str, source_scene_ids: list[str]
) -> list[Any]
```

Merge scene markers from source scenes to target scene.

This utility method copies all markers from one or more source scenes to a target scene. Useful when consolidating duplicate scenes or merging content.

Parameters:

| Name               | Type        | Description                                   | Default    |
| ------------------ | ----------- | --------------------------------------------- | ---------- |
| `target_scene_id`  | `str`       | The ID of the target scene to copy markers to | *required* |
| `source_scene_ids` | `list[str]` | List of source scene IDs to copy markers from | *required* |

Returns:

| Type        | Description                                                       |
| ----------- | ----------------------------------------------------------------- |
| `list[Any]` | List of SceneMarker objects that were created on the target scene |

Examples:

Merge markers from a single source:

```python theme={null}
markers = await client.merge_scene_markers(
    target_scene_id="123",
    source_scene_ids=["456"]
)
print(f"Copied {len(markers)} markers to target scene")
```

Merge markers from multiple sources:

```python theme={null}
markers = await client.merge_scene_markers(
    target_scene_id="123",
    source_scene_ids=["456", "789", "101"]
)
for marker in markers:
    print(f"Marker: {marker.title} at {marker.seconds}s")
```

Use with scene merge workflow:

```python theme={null}
# First merge the scenes
merged = await client.scene_merge({
    "source": ["source1", "source2"],
    "destination": "target"
})

# Then copy markers
markers = await client.merge_scene_markers(
    target_scene_id="target",
    source_scene_ids=["source1", "source2"]
)
```

### find\_duplicate\_scenes\_wrapper

```python theme={null}
find_duplicate_scenes_wrapper(
    distance: int = 0, duration_diff: float | None = None
) -> list[list[Scene]]
```

Find duplicate scenes with sensible default parameters.

This is a convenience wrapper around find\_duplicate\_scenes() that provides better defaults for common use cases. A distance of 0 finds exact phash matches (true duplicates), while higher values find similar scenes.

Parameters:

| Name            | Type            | Description                                                                                                                                                                                                                                                  | Default |
| --------------- | --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------- |
| `distance`      | `int`           | Maximum phash distance (default: 0 for exact duplicates) - 0: Exact phash matches (identical frames) - 1-5: Very similar scenes (same content, different encode) - 6-10: Similar scenes (same source, different quality) - 11+: Potentially different scenes | `0`     |
| `duration_diff` | `float \| None` | Maximum duration difference in seconds (default: None) - None: No duration filtering - 0.0: Exact duration match - 1.0-10.0: Similar duration (accounts for encoding differences) - 10.0+: Loose duration matching                                           | `None`  |

Returns:

| Type                | Description                                                          |
| ------------------- | -------------------------------------------------------------------- |
| `list[list[Scene]]` | List of scene groups, where each group is a list of duplicate scenes |

Examples:

Find exact duplicates (phash distance = 0):

```python theme={null}
duplicates = await client.find_duplicate_scenes_wrapper()
for group in duplicates:
    print(f"Found {len(group)} exact duplicates:")
    for scene in group:
        print(f"  - {scene.title}")
```

Find similar scenes (allow small phash differences):

```python theme={null}
similar = await client.find_duplicate_scenes_wrapper(distance=5)
for group in similar:
    print(f"Found {len(group)} similar scenes")
```

Find duplicates with similar duration:

```python theme={null}
duplicates = await client.find_duplicate_scenes_wrapper(
    distance=0,
    duration_diff=2.0  # Within 2 seconds
)
```

Use in cleanup workflow:

```python theme={null}
# Find exact duplicates
duplicates = await client.find_duplicate_scenes_wrapper()

for group in duplicates:
    # Keep the first scene, delete the rest
    to_delete = [scene.id for scene in group[1:]]
    if to_delete:
        await client.scenes_destroy({
            "ids": to_delete,
            "delete_file": True
        })
```
