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

# Rendering media

> Show participant video with DailyVideo, play audio with DailyAudio, and read track state with useMediaTrack.

Media is the one part of a call that has to touch the DOM: a video track needs a `<video>` element, an audio track needs an `<audio>` element. Daily React provides components that own that work so your render stays declarative.

## Render video with DailyVideo

[`DailyVideo`](/reference/daily-react/daily-video) renders a `<video>` for a participant's track. Give it a `sessionId` and a track `type`:

```jsx theme={null}
import { DailyVideo } from '@daily-co/daily-react';

function Tile({ sessionId }) {
  return <DailyVideo sessionId={sessionId} type="video" automirror />;
}
```

Useful props:

* `type` — `'video'` (camera, the default) or `'screenVideo'` (screen share).
* `automirror` — mirrors the local camera, the convention users expect when seeing themselves.
* `fit` — `'contain'` (default) or `'cover'`, mapping to CSS `object-fit`.
* `playableStyle` — styles applied only while the video is actually playing, handy for hiding the element or showing a placeholder when the camera is off.

### Style from the data attributes

`DailyVideo` renders data attributes you can target with CSS instead of reaching into props for conditional styling: `data-playable`, `data-local`, `data-mirrored`, `data-session-id`, `data-subscribed`, and `data-video-type`. For example, dim a tile until its video is playable:

```css theme={null}
[data-playable='false'] {
  opacity: 0.4;
}
```

## Play audio with DailyAudio

Render exactly one [`DailyAudio`](/reference/daily-react/daily-audio) for the whole call. It plays all remote `audio` and `screenAudio` tracks, manages a pool of speaker slots, and handles the autoplay failures that browsers throw at you:

```jsx theme={null}
import { DailyAudio } from '@daily-co/daily-react';

function Call() {
  return (
    <>
      <Grid />
      <DailyAudio />
    </>
  );
}
```

<Warning>
  Do not render one `DailyAudio` per tile. It is a single, call-wide component. Use [`DailyAudioTrack`](#custom-audio-with-dailyaudiotrack) if you genuinely need per-participant audio elements.
</Warning>

By default `DailyAudio` keeps up to 5 speaker slots; raise it with `maxSpeakers`. Handle playback failures with `onPlayFailed`:

```jsx theme={null}
const onPlayFailed = useCallback((e) => {
  console.error(`Audio play() failed for ${e.sessionId}`, e.target);
}, []);

return <DailyAudio maxSpeakers={8} onPlayFailed={onPlayFailed} />;
```

To reach the underlying `<audio>` elements, for example to set output volume, pass a `ref` and use its methods such as `getAllAudio()` and `getAudioBySessionId(sessionId)`.

## Custom audio with DailyAudioTrack

When you need to compose audio yourself, [`DailyAudioTrack`](/reference/daily-react/daily-audio-track) renders a single `<audio>` for one participant and track type. Most apps should use `DailyAudio` instead; reach for `DailyAudioTrack` only when you need direct control over each element:

```jsx theme={null}
import { DailyAudioTrack, useParticipantIds } from '@daily-co/daily-react';

function CustomAudio() {
  const remoteIds = useParticipantIds({ filter: 'remote' });
  return remoteIds.map((id) => <DailyAudioTrack key={id} sessionId={id} />);
}
```

## Read track state with useMediaTrack

When you need the track itself or its state rather than a rendered element, use [`useMediaTrack`](/reference/daily-react/use-media-track). It returns the [`MediaTrackState`](/reference/daily-js/types/daily-track-state) plus an `isOff` convenience boolean:

```jsx theme={null}
import { useMediaTrack } from '@daily-co/daily-react';

function CameraStatus({ sessionId }) {
  const video = useMediaTrack(sessionId, 'video');
  return <span>{video.isOff ? 'Camera off' : 'Camera on'}</span>;
}
```

There are convenience hooks for each track type: `useVideoTrack`, `useAudioTrack`, `useScreenVideoTrack`, and `useScreenAudioTrack`, each taking just a `sessionId`.

```jsx theme={null}
import { useVideoTrack } from '@daily-co/daily-react';

const video = useVideoTrack(sessionId); // same as useMediaTrack(sessionId, 'video')
```

<Tip>
  Use `useMediaTrack` to drive placeholders: when `isOff` is true, render an avatar instead of the `<video>`. To attach a track to your own element you can read `track.persistentTrack`, but prefer `DailyVideo` unless you have a specific reason not to.
</Tip>

## A complete tile

Putting video, name, and a mic indicator together:

```jsx theme={null}
import {
  DailyVideo,
  useMediaTrack,
  useParticipantProperty,
} from '@daily-co/daily-react';

function Tile({ sessionId }) {
  const userName = useParticipantProperty(sessionId, 'user_name');
  const audio = useMediaTrack(sessionId, 'audio');

  return (
    <div style={{ position: 'relative', width: 320 }}>
      <DailyVideo
        sessionId={sessionId}
        type="video"
        automirror
        fit="cover"
        style={{ width: '100%', borderRadius: 8, background: '#000' }}
      />
      <span>
        {userName || 'Guest'} {audio.isOff && '🔇'}
      </span>
    </div>
  );
}
```

## Next steps

<CardGroup cols={2}>
  <Card title="Devices" icon="microphone" href="/docs/daily-react/docs/devices">
    Let users pick and toggle their camera and mic.
  </Card>

  <Card title="Screen sharing" icon="display" href="/docs/daily-react/docs/screen-sharing">
    Render and control screen shares.
  </Card>
</CardGroup>
