# Video mixing (/en/realtime-media/rtc-server-sdk/build/build-core-media-features/video-mixing)

> For AI agents: see the complete documentation index at [llms.txt](/llms.txt).

Server Gateway supports video mixing, enabling you to combine video tracks from multiple remote or local users and output the video in a customized format. This feature can be used to add watermarks, create picture-in-picture layouts or produce split-screen and multi-view displays.

## Implementation [#implementation]

Refer to the following steps to implement video mixing.

1. Create an `IVideoMixerSource` object.

   ```cpp
   agora::agora_refptr<agora::rtc::IVideoMixerSource> videoMixer = factory->createVideoMixer();
   ```

2. Call `createMixedVideoTrack` to create a mixed video track. Use the mixed video track to register a video frame observer.

   ```cpp
   agora::agora_refptr<agora::rtc::ILocalVideoTrack> mixVideoTrack =
     service->createMixedVideoTrack(videoMixer);
   if (!mixVideoTrack) {
       AG_LOG(ERROR, "Failed to create video track!");
       return -1;
   }
   agora::rtc::VideoEncoderConfiguration encoderConfig;
   encoderConfig.codecType = agora::rtc::VIDEO_CODEC_H264;
   encoderConfig.dimensions.width = 1920;
   encoderConfig.dimensions.height = 1080;
   encoderConfig.frameRate = 15;

   mixVideoTrack->setVideoEncoderConfiguration(encoderConfig);

   // Register video frame observer to receive video stream
   agora::agora_refptr<agora::rtc::IVideoSinkBase> yuvFrameObserver =
     new agora::RefCountedObject<YuvFrameObserver>(options.videoFile);

   mixVideoTrack->addRenderer(yuvFrameObserver.get());
   ```

3. Add the video track to `IVideoMixerSource` for video mixing.

   ```cpp
   if (remote_video_track_ && video_mixer_ && enable_video_mix_) {
       video_mixer_->addVideoTrack(userId, remote_video_track_);
       remote_video_track_map_[std::string(userId)] = remote_video_track_;
   }
   ```

4. When the SDK decodes the first YUV frame, call `setBackground` to set the background and refresh the `IVideoMixerSource` object.

   ```cpp
   remote_source_map_[std::string(userId)] = calculate_layout(width,height);
   for (auto it = remote_source_map_.begin(); it != remote_source_map_.end(); it++) {
       video_mixer_->setStreamLayout(it->first.c_str(), it->second);
   }
   video_mixer_->setBackground(1920, 1080, 15);
   video_mixer_->refresh();
   ```
