Skip to main content

Stream media to a channel

Users often need to play video and audio files during online social and business interactions. Video SDK enables you to add media playing functionality to your app. This page shows you how to use the media player classes in Video SDK to enable your users to publish media files to a channel.

Understand the tech

When a user selects a media file to play, you open the media file using a media player instance. When the file is ready to be played, you setup the local video container to display the media player output. You update the channel media options to start publishing the media player stream, then stop publishing the camera and microphone streams. The remote user sees the camera and microphone streams of the media publishing user replaced by media streams.

The following figure shows the workflow you need to integrate media player functionality into your app.

play media

Prerequisites

In order to follow this procedure you must have:

  • An Agora account and project.

  • A computer with Internet access.

    Ensure that no firewall is blocking your network communication.

Project setup

To create the environment necessary to implement playing media files into your app, open the SDK quickstart Broadcast Streaming project you created previously.

Add a media player to your app

This section shows how to use the Video SDK to implement a media player into your app, step-by-step.

Implement the user interface

In a real-word application, you provide several buttons to enable a user to open, play, pause and stop playing files in the media player. In this simple example, you use a single Button to demonstrate the basic media player functions. You also add a ProgressBar to display the play progress to the user.

To add the UI elements, take the following steps:

  1. Add a slider control to show media progress

    To add a slider control to the UI, take the following steps:

    1. Go to menu View > Other Windows > Resource View.

      If the Resource View window isn't the top-most window, select the Resource View tab to bring it to the top.

    2. To view the dialog resources, in Resource View, go to AgoraImplementation.rc > Dialog and double-click IDD_AGORAIMPLEMENTATION_DIALOG.

      The resource opens inside the Dialog Editor.

    3. To open Toolbox, go to menu View > ToolBox.

    4. From ToolBox, drag Slider Control and drop it onto the surface of the Dialog Editor.

      You see a slider in your Dialog Editor.

  2. Add a Button to the UI

    1. From ToolBox, drag Button and drop it onto the surface of the Dialog Editor

    2. To change the button label, in Properties, update the Caption field with Open Media File.

Handle the system logic

To setup your project to use the media player APIs and access the UI elements, take the following steps:

  1. Add the required libraries

    To import the required Agora libraries, in AgoraImplementationDlg.h, add the following header files at the start:

    #include <IAgoraMediaPlayer.h>
    #include <IAgoraMediaPlayerSource.h>
    using namespace agora::base;
    using namespace agora::media::base;
    Copy
  2. Declare the variables you need

    To create and manage an instance of the media player and access the UI elements, in AgoraImplementationDlg.h, add the following to CAgoraImplementationDlg:

    IMediaPlayer *mediaPlayer; // Instance of the media player
    BOOL isMediaPlaying = false;
    long mediaDuration = 0;
    // In a real world app, you declare the media location variable with an empty string
    // and update it when a user chooses a media file from a local or remote source.
    std::string mediaLocation =
    "https://www.appsloveworld.com/wp-content/uploads/2018/10/640.mp4";
    MediaPlayerSourceObserver mediaPlayerEventHandler;
    CButton *mediaButton;
    CSliderCtrl *mediaProgressBar;
    Copy
  3. Reference the UI elements

    In AgoraImplementationDlg.h, add the following at the end of OnInitDialog:

    mediaButton = (CButton*)GetDlgItem(IDC_BUTTON3);
    mediaProgressBar = (CSliderCtrl*)GetDlgItem(IDC_SLIDER1);
    Copy

Implement media player functions

To implement playing and publishing media files in your app, take the following steps:

  1. Open, play and pause media files

    When a user presses the button for the first time, you create an instance of the media player, set its mediaPlayerObserver to receive the callbacks, and open the media file. When the user presses the button again, you play the media file. On subsequent button presses, you pause or resume playing the media file alternately. To implement this workflow, in Dialog Editor, double-click Open Media File. Dialog Editor automatically creates and opens an event listener for you. Add the following code to the event listener you just created:

    // Initialize the mediaPlayer and open a media file
    if (mediaPlayer == NULL) {
    // Create an instance of the media player
    mediaPlayer = agoraEngine->createMediaPlayer().get();
    // Set the mediaPlayerObserver to receive callbacks
    mediaPlayer->registerPlayerSourceObserver(&mediaPlayerEventHandler);
    // Open the media file
    mediaPlayer->open(mediaLocation.c_str(), 0);
    // Update the UI.
    mediaButton->SetWindowText(L"Opening File...");
    return;
    }
    // Set up the local video container to handle the media player output
    // or the camera stream, alternately.
    isMediaPlaying = ~isMediaPlaying;
    // Set the stream publishing options.
    updateChannelPublishOptions(isMediaPlaying);
    // Display the stream locally.
    setupLocalVideo(isMediaPlaying);

    if (isMediaPlaying) { // Start or resume playing media
    if (mediaPlayer->getState() == PLAYER_STATE_OPEN_COMPLETED) {
    mediaPlayer->play();
    }
    else if (mediaPlayer->getState() == PLAYER_STATE_PAUSED) {
    mediaPlayer->resume();
    }
    mediaButton->SetWindowText(L"Pause");
    }
    else {
    if (mediaPlayer->getState() == PLAYER_STATE_PLAYING) {
    // Pause media file
    mediaPlayer->pause();
    mediaButton->SetWindowText(L"Resume");
    }
    }
    Copy
  2. Manage media player callbacks

    The IMediaPlayerObserver implements media player callbacks. You create an instance of IMediaPlayerObserver and register it with the media player instance. When the player state changes, you take appropriate actions to update the UI in onPlayerStateChanged. You use the onPositionChanged callback to update the progress bar. To setup an event handler, take the following steps:

    1. In AgoraImplementationDlg.h, add the following class before AgoraEventHandler:

      class MediaPlayerSourceObserver : public IMediaPlayerSourceObserver
      {
      public:
      //set the message notify window handler
      void SetMsgReceiver(HWND hWnd) { m_hMsgHanlder = hWnd; }
      virtual void onPlayerSourceStateChanged(MEDIA_PLAYER_STATE state, MEDIA_PLAYER_ERROR ec)
      {
      // Call OnEIDMediaPlayerStateChanged when the state of the player changes.
      ::PostMessage(m_hMsgHanlder, WM_MSGID(PLAYER_STATE_CHANGED), (WPARAM)state, (LPARAM)ec);
      }
      virtual void onPositionChanged(int64_t position)
      {
      // Call OnEIDMediaPlayerPositionChanged to display the media file position on the progress bar.
      ::PostMessage(m_hMsgHanlder, WM_MSGID(PLAYER_POSITION_CHANGED), (LPARAM)position, NULL);
      }
      virtual void onPlayerEvent(MEDIA_PLAYER_EVENT event, int64_t elapsedTime, const char* message) override
      {
      // Required to implement IMediaPlayerObserver.
      }
      virtual void onMetaData(const void* data, int length)
      {
      // Required to implement IMediaPlayerObserver
      }
      virtual void onPlayBufferUpdated(int64_t playCachedBuffer)
      {
      // Required to implement IMediaPlayerObserver
      }
      virtual void onPreloadEvent(const char* src, PLAYER_PRELOAD_EVENT event)
      {
      // Required to implement IMediaPlayerObserver
      }
      virtual void onAgoraCDNTokenWillExpire()
      {
      // Required to implement IMediaPlayerObserver
      }
      virtual void onPlayerSrcInfoChanged(const SrcInfo& from, const SrcInfo& to) override
      {
      // Required to implement IMediaPlayerSourceObserver
      }
      virtual void onPlayerInfoUpdated(const PlayerUpdatedInfo& info) override
      {
      // Required to implement IMediaPlayerObserver
      }
      virtual void onAudioVolumeIndication(int volume) override
      {
      // Required to implement IMediaPlayerObserver
      }
      virtual void onCompleted()
      {
      // Occurs when the media player finishes playing a media file.
      }
      private:
      HWND m_hMsgHanlder;
      };
      Copy
    2. In AgoraImplementationDlg.h, add the following to CAgoraImplementationDlg:

      afx_msg LRESULT OnEIDMediaPlayerStateChanged(WPARAM wParam, LPARAM lParam);
      afx_msg LRESULT OnEIDMediaPlayerPositionChanged(WPARAM wParam, LPARAM lParam);
      Copy
    3. In AgoraImplementationDlg.cpp, add the following after the list of header files:

      #define PLAYER_POSITION_CHANGED 0x00000005
      #define PLAYER_MEDIA_COMPLETED 0x00000006
      Copy
    4. In AgoraImplementationDlg.cpp, add the following code:

      ON_MESSAGE(WM_MSGID(PLAYER_POSITION_CHANGED), &CAgoraImplementationDlg::OnEIDMediaPlayerPositionChanged)
      ON_MESSAGE(WM_MSGID(PLAYER_STATE_CHANGED), &CAgoraImplementationDlg::OnEIDMediaPlayerStateChanged)
      Copy
    5. In AgoraImplementationDlg.cpp, add the following methods before OnInitDialog:

      LRESULT CAgoraImplementationDlg::OnEIDMediaPlayerStateChanged(WPARAM wParam, LPARAM lParam)
      {
      if (wParam == PLAYER_STATE_OPEN_COMPLETED)
      {
      // Media file opened successfully
      int64_t mediaDuration;
      // Get the file duration.
      mediaPlayer->getDuration(mediaDuration);
      // Update the UI
      mediaButton->SetWindowText(L"Play Media File");
      // Set the maximum value of the control slider to mediaDuration.
      mediaProgressBar->SetRange(0, (int)mediaDuration, TRUE);
      }
      else if (wParam == PLAYER_STATE_PLAYBACK_ALL_LOOPS_COMPLETED)
      {
      isMediaPlaying = false;
      // Media file finished playing.
      mediaButton->SetWindowText(L"Load Media File");
      // Reset the progress bar.
      mediaProgressBar->SetPos(0);
      // Restore the local video view.
      setupLocalVideo(false);
      // Re-publish the local audio and video in the channel.
      updateChannelPublishOptions(false);
      // Clean up
      mediaPlayer->Release();
      mediaPlayer = NULL;
      }
      // Notify the parent window.
      ::PostMessage(GetParent()->GetSafeHwnd(), WM_MSGID(PLAYER_STATE_CHANGED), TRUE, 0);
      return 0;
      }
      LRESULT CAgoraImplementationDlg::OnEIDMediaPlayerPositionChanged(WPARAM wParam, LPARAM lParam)
      {
      // Change the progress bar tick position.
      mediaProgressBar->SetPos(wParam);
      // Notify the parent window.
      ::PostMessage(GetParent()->GetSafeHwnd(), WM_MSGID(PLAYER_POSITION_CHANGED), TRUE, 0);
      return 0;
      }
      Copy
  3. Configure Agora Engine to publish the media player stream

    You use ChannelMediaOptions and the updateChannelMediaOptions method to specify the type of stream to publish. To switch between publishing media player and camera and microphone streams, take the following steps:

    1. In AgoraImplementationDlg.h, add the following to method CAgoraImplementationDlg before afx_msg void OnClose();

      // Declare a method to publish and publish the local and media file streams.
      void updateChannelPublishOptions(BOOL value);
      Copy
    2. In AgoraImplementationDlg.cpp, add the method after OnInitDialog:

      void CAgoraImplementationDlg::updateChannelPublishOptions(BOOL publishMediaPlayer)
      {
      // You use ChannelMediaOptions to change channel media options.
      ChannelMediaOptions channelOptions;
      channelOptions.publishMediaPlayerAudioTrack = publishMediaPlayer;
      channelOptions.publishMediaPlayerVideoTrack = publishMediaPlayer;
      channelOptions.publishMicrophoneTrack = !publishMediaPlayer;
      channelOptions.publishCameraTrack = !publishMediaPlayer;
      if (publishMediaPlayer) channelOptions.publishMediaPlayerId = mediaPlayer->getMediaPlayerId();
      agoraEngine->updateChannelMediaOptions(channelOptions);
      }
      Copy
  4. Display media player output locally

    To display the media file, you call stopPreview to stop the local video preview and call setView and pass the local view window handle. To switch between displaying media player output and the camera stream, take the following steps:

    1. In AgoraImplementationDlg.h, add the following to method CAgoraImplementationDlg before afx_msg void OnClose();

      // Declare a method to switch between the local video and media file output.
      void setupLocalVideo(BOOL value);
      Copy
    2. In AgoraImplementationDlg.cpp, add the method after OnInitDialog:

      void CAgoraImplementationDlg::setupLocalVideo(BOOL forMediaPlayer)
      {
      // Pass the window handle to the engine so that it renders the local video.
      if (forMediaPlayer)
      {
      // Stop previewing the local video.
      agoraEngine->stopPreview();
      // To display the media file output, pass the local view window handle to the setView method of the IMediaPlayer class.
      mediaPlayer->setView(localView.GetSafeHwnd());
      }
      else
      {
      // Start the local video preview.
      agoraEngine->startPreview();
      }
      }
      Copy
  5. Clean up when you close the app

    To free up resources when you exit the app, add the following lines to the onDestroy method after super.onDestroy();:

    // Destroy the media player
    mediaPlayer.stop();
    mediaPlayer.unRegisterPlayerObserver(mediaPlayerObserver);
    mediaPlayer.destroy();
    Copy

Test your implementation

To ensure that you have implemented media player features into your app:

  1. Generate a temporary token in Agora Console .

  2. In your browser, navigate to the Agora web demo and update App ID, Channel, and Token with the values for your temporary token, then click Join.

  1. In Visual Studio, in AgoraImplementation.h, update appId, channelName and token with the values for your temporary token.

  2. In Visual Studio, click Local Windows Debugger. A moment later you see the project running on your development device.

    If this is the first time you run the project, you need to grant microphone and camera access to your app.

  1. Press Open Media File.

    After a short while, you see the button text changes confirming that the media file is opened successfully.

  2. Press Play Media File

    You see the media file played both locally and in the web demo app. The progress bar indicates the play progress.

  3. Press Pause

    Media publishing is paused and the camera and microphone publishing is resumed.

  4. Press Resume

    You see that the media file resumes playing.

  5. Wait for the media file to finish playing. When the progress bar reaches the end, the media player publishing is stopped and camera and microphone publishing is resumed.

Reference

This section contains information that completes the information in this page, or points you to documentation that explains other aspects to this product.

vundefined