媒体播放器
- Android
更新时间不可用
了解实时互动 RTC 在不同平台上的媒体播放器方式,包括接入流程、关键配置和平台差异。
前提条件
本文介绍如何调用媒体播放器相关的 API 播放本地或在线媒体资源,或将媒体资源分享给声网频道内的远端用户。在进行操作之前,请确保你已经在项目中实现了基本的实时音视频功能。有关详细信息,请参考实现音视频互动。
实现方法
参考如下步骤,在你的项目中使用媒体播放器:
-
初始化
RtcEngine后,创建一个IMediaPlayer对象,并调用registerPlayerObserver方法注册播放观测器。Java engine = RtcEngine.create(config); ... // 创建媒体播放器对象 mediaPlayer = engine.createMediaPlayer(); // 注册播放观测器 mediaPlayer.registerPlayerObserver(this); -
实现媒体播放器观测器的回调。根据你的需求,你可以通过
onPlayerStateChanged回调来观测播放器的状态,通过onPositionChanged回调来获取当前媒体文件的播放进度,通过onPlayerEvent来获取播放器事件。Java @Override // 报告播放器的状态 public void onPlayerStateChanged(io.agora.mediaplayer.Constants.MediaPlayerState mediaPlayerState, io.agora.mediaplayer.Constants.MediaPlayerError mediaPlayerError) { Log.e(TAG, "onPlayerStateChanged mediaPlayerState " + mediaPlayerState); Log.e(TAG, "onPlayerStateChanged mediaPlayerError " + mediaPlayerError); if (mediaPlayerState.equals(PLAYER_STATE_OPEN_COMPLETED)) { setMediaPlayerViewEnable(true); } else if (mediaPlayerState.equals(PLAYER_STATE_IDLE) || mediaPlayerState.equals(PLAYER_STATE_PLAYBACK_COMPLETED) ) { setMediaPlayerViewEnable(false); } } @Override // 报告当前播放进度 public void onPositionChanged(long position) { Log.e(TAG, "onPositionChanged position " + position); if (playerDuration > 0) { final int result = (int) ((float) position / (float) playerDuration * 100); handler.post(new Runnable() { @Override public void run() { progressBar.setProgress(Long.valueOf(result).intValue()); } }); } } @Override // 报告播放器事件 public void onPlayerEvent(io.agora.mediaplayer.Constants.MediaPlayerEvent mediaPlayerEvent) { Log.e(TAG, " onPlayerEvent mediaPlayerEvent " + mediaPlayerEvent); } -
调用
setupLocalVideo方法渲染本地媒体播放视图。Java VideoCanvas videoCanvas = new VideoCanvas(surfaceView, Constants.RENDER_MODE_HIDDEN, Constants.VIDEO_MIRROR_MODE_AUTO, Constants.VIDEO_SOURCE_MEDIA_PLAYER, mediaPlayer.getMediaPlayerId(), 0); engine.setupLocalVideo(videoCanvas); -
调用
joinChannel加入频道时,通过options参数设置媒体播放器 ID、发布媒体播放器的音视频、将媒体资源分享给声网频道内的远端用户。Java private ChannelMediaOptions options = new ChannelMediaOptions(); ... options.publishMediaPlayerId = mediaPlayer.getMediaPlayerId(); options.publishMediaPlayerAudioTrack = true; options.publishMediaPlayerVideoTrack = true; int res = engine.joinChannel(accessToken, channelId, 0, options); -
调用
open打开本地或在线媒体文件。Java mediaPlayer.open(url, 0); -
调用
play播放媒体文件。注意
请在收到
onPlayerStateChanged回调报告播放状态为PLAYER_STATE_OPEN_COMPLETED后再调用play方法播放媒体文件。Java mediaPlayer.play(); -
当用户离开频道时,调用
stop停止播放、调用unRegisterPlayerObserver取消注册播放观测器、调用destroy销毁媒体播放器并释放已分配的资源。Java mediaPlayer.stop(); mediaPlayer.unRegisterPlayerObserver(this); mediaPlayer.destroy();
参考信息
示例项目
声网提供了开源的示例项目供你参考,你可以前往下载或查看其中的源代码。
支持的格式
声网的媒体播放器支持下列格式及协议:
视频编码格式
- H.263、H.264、H.265、MPEG4、MPEG2、RMVB、Theora、VP3、VP8、AVS、WMV
音频编码格式
- WAV、MP2、MP3、AAC、OPUS、FLAC、Vorbis、AMR-NB、AMR-WB、WMA v1、WMA v2
容器格式
- WAV、FLAC、OGG、MOV、ASF、FLV、MP3、MP4、MPEG-TS、Matroska (MKV)、AVI、ASS、CONCAT、DTS、AVS
支持的协议
- HTTP、HTTPS、RTMP、HLS、RTP、RTSP
API 参考
本文介绍如何调用媒体播放器相关的 API 播放本地或在线媒体资源,或将媒体资源同步分享给声网频道内的远端用户。
前提条件
在进行操作之前,请确保你已经在项目中实现了基本的实时音视频功能。详见实现音视频互动。
实现方法
参考如下步骤,在你的项目中使用媒体播放器:
-
初始化
AgoraRtcEngineKit后,调用createMediaPlayer创建AgoraRtcMediaPlayerProtocol对象。Swift // 初始化 AgoraRtcEngineKit agoraKit = AgoraRtcEngineKit.sharedEngine(with: config, delegate: self) // 创建 mediaPlayerKit 对象 mediaPlayerKit = agoraKit.createMediaPlayer(with: self) -
实现媒体播放器回调。根据你的需求,你可以通过
didChangedToState回调来观测播放器的状态,通过didChangedToPosition回调来获取当前媒体文件的播放进度。Swift extension MediaPlayerMain: AgoraRtcMediaPlayerDelegate { // 报告播放器的状态 func agoraRtcMediaPlayer(_ playerKit: AgoraRtcMediaPlayerProtocol, didChangedTo state: AgoraMediaPlayerState, error: AgoraMediaPlayerError) { LogUtils.log(message: "player rtc channel publish helper state changed to: \(state.rawValue), error: \(error.rawValue)", level: .info) DispatchQueue.main.async { [weak self] in guard let weakself = self else { return } switch state { case .failed: weakself.showAlert(message: "media player error: \(error.rawValue)") break case .openCompleted: let duration = weakself.mediaPlayerKit.getDuration() weakself.playerControlStack.isHidden = false weakself.playerDurationLabel.text = "\(String(format: "%02d", duration / 60)) : \(String(format: "%02d", duration % 60))" weakself.playerProgressSlider.setValue(0, animated: true) break case .stopped: weakself.playerControlStack.isHidden = true weakself.playerProgressSlider.setValue(0, animated: true) weakself.playerDurationLabel.text = "00 : 00" break default: break } } } // 报告当前的播放进度 func agoraRtcMediaPlayer(_ playerKit: AgoraRtcMediaPlayerProtocol, didChangedToPosition position: Int) { let duration = Float(mediaPlayerKit.getDuration() * 1000) var progress: Float = 0 var left: Int = 0 if duration > 0 { progress = Float(mediaPlayerKit.getPosition()) / duration left = Int((mediaPlayerKit.getDuration() * 1000 - mediaPlayerKit.getPosition()) / 1000) } DispatchQueue.main.async { [weak self] in guard let weakself = self else { return } weakself.playerDurationLabel.text = "\(String(format: "%02d", left / 60)) : \(String(format: "%02d", left % 60))" if !weakself.playerProgressSlider.isTouchInside { weakself.playerProgressSlider.setValue(progress, animated: true) } } } } -
调用
setupLocalVideo渲染本地媒体播放视图。Swift mediaPlayerKit.setView(localVideo.videoView) let videoCanvas = AgoraRtcVideoCanvas() videoCanvas.view = localVideo.videoView videoCanvas.renderMode = .hidden videoCanvas.sourceType = .mediaPlayer videoCanvas.sourceId = mediaPlayerKit.getMediaPlayerId() agoraKit.setupLocalVideo(videoCanvas) -
调用
joinChannelByToken加入频道时,通过mediaOptions设置媒体播放器 ID,发布媒体播放器的音视频,将媒体资源分享给声网频道内的远端用户。Swift let option1 = AgoraRtcChannelMediaOptions() ... option1.publishMediaPlayerId = .of((Int32)(mediaPlayerKit.getMediaPlayerId())) -
调用
open打开本地或在线媒体文件。Swift mediaPlayerKit.open(url, startPos: 0) -
调用
play播放媒体文件。注意
请在收到
didChangedToState回调报告播放状态为AgoraMediaPlayerStateOpenCompleted后再调用play方法播放媒体文件。Swift mediaPlayerKit.play() -
当用户离开频道时,调用
stop停止播放、调用destroyMediaPlayer销毁媒体播放器、取消注册播放观测器,并销毁分配的资源。Swift mediaPlayerKit.stop() agoraKit.destroyMediaPlayer(mediaPlayerKit)
参考信息
示例项目
声网提供了开源的示例项目供你参考,你可以前往下载或查看其中的源代码。
支持的格式
声网的媒体播放器支持下列格式及协议:
视频编码格式
- H.263、H.264、H.265、MPEG4、MPEG2、RMVB、Theora、VP3、VP8、AVS、WMV
音频编码格式
- WAV、MP2、MP3、AAC、OPUS、FLAC、Vorbis、AMR-NB、AMR-WB、WMA v1、WMA v2
容器格式
- WAV、FLAC、OGG、MOV、ASF、FLV、MP3、MP4、MPEG-TS、Matroska (MKV)、AVI、ASS、CONCAT、DTS、AVS
支持的协议
- HTTP、HTTPS、RTMP、HLS、RTP、RTSP
API 参考
本文介绍如何调用媒体播放器相关的 API 播放本地或在线媒体资源,或将媒体资源同步分享给声网频道内的远端用户。
前提条件
在进行操作之前,请确保你已经在项目中实现了基本的实时音视频功能。详见实现音视频互动。
实现方法
参考如下步骤,在你的项目中使用媒体播放器:
-
初始化
AgoraRtcEngineKit后,调用createMediaPlayer创建AgoraRtcMediaPlayerProtocol对象。Swift // 初始化 AgoraRtcEngineKit agoraKit = AgoraRtcEngineKit.sharedEngine(with: config, delegate: self) // 创建 mediaPlayerKit 对象 mediaPlayerKit = agoraKit.createMediaPlayer(with: self) -
实现媒体播放器回调。根据你的需求,你可以通过
didChangedToState回调来观测播放器的状态,通过didChangedToPosition回调来获取当前媒体文件的播放进度。Swift extension MediaPlayerMain: AgoraRtcMediaPlayerDelegate { // 报告播放器的状态 func agoraRtcMediaPlayer(_ playerKit: AgoraRtcMediaPlayerProtocol, didChangedTo state: AgoraMediaPlayerState, error: AgoraMediaPlayerError) { LogUtils.log(message: "player rtc channel publish helper state changed to: \(state.rawValue), error: \(error.rawValue)", level: .info) DispatchQueue.main.async { [weak self] in guard let weakself = self else { return } switch state { case .failed: weakself.showAlert(message: "media player error: \(error.rawValue)") break case .openCompleted: let duration = weakself.mediaPlayerKit.getDuration() weakself.playerControlStack.isHidden = false weakself.playerDurationLabel.text = "\(String(format: "%02d", duration / 60)) : \(String(format: "%02d", duration % 60))" weakself.playerProgressSlider.setValue(0, animated: true) break case .stopped: weakself.playerControlStack.isHidden = true weakself.playerProgressSlider.setValue(0, animated: true) weakself.playerDurationLabel.text = "00 : 00" break default: break } } } // 报告当前的播放进度 func agoraRtcMediaPlayer(_ playerKit: AgoraRtcMediaPlayerProtocol, didChangedToPosition position: Int) { let duration = Float(mediaPlayerKit.getDuration() * 1000) var progress: Float = 0 var left: Int = 0 if duration > 0 { progress = Float(mediaPlayerKit.getPosition()) / duration left = Int((mediaPlayerKit.getDuration() * 1000 - mediaPlayerKit.getPosition()) / 1000) } DispatchQueue.main.async { [weak self] in guard let weakself = self else { return } weakself.playerDurationLabel.text = "\(String(format: "%02d", left / 60)) : \(String(format: "%02d", left % 60))" if !weakself.playerProgressSlider.isTouchInside { weakself.playerProgressSlider.setValue(progress, animated: true) } } } } -
调用
setupLocalVideo渲染本地媒体播放视图。Swift mediaPlayerKit.setView(localVideo.videoView) let videoCanvas = AgoraRtcVideoCanvas() videoCanvas.view = localVideo.videoView videoCanvas.renderMode = .hidden videoCanvas.sourceType = .mediaPlayer videoCanvas.sourceId = mediaPlayerKit.getMediaPlayerId() agoraKit.setupLocalVideo(videoCanvas) -
调用
joinChannelByToken加入频道时,通过mediaOptions设置媒体播放器 ID,发布媒体播放器的音视频,将媒体资源分享给声网频道内的远端用户。Swift let option1 = AgoraRtcChannelMediaOptions() ... option1.publishMediaPlayerId = .of((Int32)(mediaPlayerKit.getMediaPlayerId())) -
调用
open打开本地或在线媒体文件。Swift mediaPlayerKit.open(url, startPos: 0) -
调用
play播放媒体文件。注意
请在收到
didChangedToState回调报告播放状态为AgoraMediaPlayerStateOpenCompleted后再调用play方法播放媒体文件。Swift mediaPlayerKit.play() -
当用户离开频道时,调用
stop停止播放、调用destroyMediaPlayer销毁媒体播放器、取消注册播放观测器,并销毁分配的资源。Swift mediaPlayerKit.stop() agoraKit.destroyMediaPlayer(mediaPlayerKit)
参考信息
示例项目
声网提供了开源的示例项目供你参考,你可以前往下载或查看其中的源代码。
支持的格式
声网的媒体播放器支持下列格式及协议:
视频编码格式
- H.263、H.264、H.265、MPEG4、MPEG2、RMVB、Theora、VP3、VP8、AVS、WMV
音频编码格式
- WAV、MP2、MP3、AAC、OPUS、FLAC、Vorbis、AMR-NB、AMR-WB、WMA v1、WMA v2
容器格式
- WAV、FLAC、OGG、MOV、ASF、FLV、MP3、MP4、MPEG-TS、Matroska (MKV)、AVI、ASS、CONCAT、DTS、AVS
支持的协议
- HTTP、HTTPS、RTMP、HLS、RTP、RTSP
API 参考
本文介绍如何调用媒体播放器相关的 API 播放本地或在线媒体资源,或将媒体资源分享给声网频道内的远端用户。
前提条件
在进行操作之前,请确保你已经在项目中实现了基本的实时音视频功能。有关详细信息,请参考实现音视频互动。
实现方法
参考如下步骤,在你的项目中使用媒体播放器:
-
初始化
IRtcEngine后,创建一个IMediaPlayer对象。C++ void CAgoraMediaPlayer::InitMediaPlayerKit() { // 创建声网媒体播放器 m_mediaPlayer = m_rtcEngine->createMediaPlayer().get(); m_lstInfo.InsertString(m_lstInfo.GetCount(), _T("createAgoraMediaPlayer")); m_lstInfo.InsertString(m_lstInfo.GetCount(), _T("mediaplayer initialize")); // 设置播放器渲染视图 RECT rc = {0}; m_localVideoWnd.GetWindowRect(&rc); int ret = m_mediaPlayer->setView( (agora::media::base::view_t)m_localVideoWnd.GetSafeHwnd()); // 设置接收播放器事件的窗口 m_mediaPlayerEvent.SetMsgReceiver(m_hWnd); } -
调用
registerPlayerSourceObserver方法注册播放观测器。C++ void CAgoraMediaPlayer::OnBnClickedButtonJoinchannel() { // ... // 注册播放观测器 ret = m_mediaPlayer->registerPlayerSourceObserver(&m_mediaPlayerEvent); m_lstInfo.InsertString(m_lstInfo.GetCount(), _T("registerPlayerSourceObserver")); if (0 == m_rtcEngine->joinChannel(APP_TOKEN, szChannelId.c_str(), 0, options)) { strInfo.Format(_T("join channel %s, use ChannelMediaOptions"), getCurrentTime()); } } else { // 取消注册播放观测器 ret = m_mediaPlayer->unregisterPlayerSourceObserver(&m_mediaPlayerEvent); m_lstInfo.InsertString(m_lstInfo.GetCount(), _T("registerPlayerSourceObserver")); // leave channel in the engine. if (0 == m_rtcEngine->leaveChannel()) { strInfo.Format(_T("leave channel %s"), getCurrentTime()); } } m_lstInfo.InsertString(m_lstInfo.GetCount(), strInfo); -
实现媒体播放器观测器的回调。
C++ // 报告播放器状态改变 LRESULT CAgoraMediaPlayer::OnmediaPlayerStateChanged(WPARAM wParam, LPARAM lParam) { CString strState; CString strError; switch ((agora::media::base::MEDIA_PLAYER_STATE)wParam) { case agora::media::base::PLAYER_STATE_OPEN_COMPLETED: strState = _T("PLAYER_STATE_OPEN_COMPLETED"); m_mediaPlayerState = mediaPLAYER_OPEN; int64_t duration; m_mediaPlayer->getDuration(duration); m_sldVideo.SetRangeMax((int)duration); break; // ... } switch ((agora::media::base::MEDIA_PLAYER_ERROR)lParam) { case agora::media::base::PLAYER_ERROR_URL_NOT_FOUND: strError = _T("PLAYER_ERROR_URL_NOT_FOUND"); break; // ... } CString strInfo; strInfo.Format(_T("sta:%s,\nerr:%s"), strState, strError); m_lstInfo.InsertString(m_lstInfo.GetCount(), strInfo); return TRUE; } // 报告当前播放进度 LRESULT CAgoraMediaPlayer::OnmediaPlayerPositionChanged(WPARAM wParam, LPARAM lParam) { int64_t *p = (int64_t *)wParam; m_sldVideo.SetPos((int)*p); delete p; return TRUE; } -
调用
joinChannel加入频道时,通过options参数设置媒体播放器 ID,发布媒体播放器的音视频,将媒体资源分享给声网频道内的远端用户。C++ void CAgoraMediaPlayer::OnBnClickedButtonPublishVideo() { if (m_publishMeidaplayer) { ChannelMediaOptions op; op.clientRoleType = CLIENT_ROLE_BROADCASTER; op.publishMediaPlayerVideoTrack = false; op.publishMediaPlayerAudioTrack = false; op.publishMediaPlayerId = m_mediaPlayer->getMediaPlayerId(); int ret = m_rtcEngine->updateChannelMediaOptions(op); ChannelMediaOptions op2; op2.clientRoleType = CLIENT_ROLE_BROADCASTER; op2.publishCameraTrack = true; ret = m_rtcEngine->updateChannelMediaOptions(op2); m_publishMeidaplayer = false; } else { ChannelMediaOptions options; options.clientRoleType = CLIENT_ROLE_BROADCASTER; options.publishMediaPlayerVideoTrack = true; options.publishMediaPlayerAudioTrack = true; options.publishMediaPlayerId = m_mediaPlayer->getMediaPlayerId(); options.publishCameraTrack = false; options.publishAudioTrack = false; options.autoSubscribeAudio = false; options.autoSubscribeVideo = false; m_rtcEngine->updateChannelMediaOptions(options); m_publishMeidaplayer = true; } } -
调用
open打开本地或在线媒体文件。C++ void CAgoraMediaPlayer::OnBnClickedButtonOpen() { CString strUrl; CString strInfo; m_edtVideoSource.GetWindowText(strUrl); std::string tmp = cs2utf8(strUrl); switch (m_mediaPlayerState) { case mediaPLAYER_READY: case mediaPLAYER_STOP: if (tmp.empty()) { AfxMessageBox(_T("you can fill video source.")); return; } // 打开媒体文件 m_mediaPlayer->open(tmp.c_str(), 0); break; default: m_lstInfo.InsertString(m_lstInfo.GetCount(), _T("can not open player.")); break; } } -
调用
play播放媒体文件。如果你需要暂停播放文件,可调用pause方法。注意
请在收到
onPlayerSourceStateChanged回调报告播放状态为PLAYER_STATE_OPEN_COMPLETED后再调用play方法播放媒体文件。C++ void CAgoraMediaPlayer::OnBnClickedButtonPlay() { int ret; switch (m_mediaPlayerState) { case mediaPLAYER_PAUSE: case mediaPLAYER_OPEN: // 播放媒体文件 ret = m_mediaPlayer->play(); if (ret == 0) { m_mediaPlayerState = mediaPLAYER_PLAYING; } break; case mediaPLAYER_PLAYING: // 暂停播放 ret = m_mediaPlayer->pause(); if (ret == 0) { m_mediaPlayerState = mediaPLAYER_PAUSE; } break; default: break; } } -
当用户离开频道时,停止播放、销毁媒体播放器、取消注册播放观测器,并销毁分配的资源。
C++ void CAgoraMediaPlayer::OnBnClickedButtonStop() { if (m_mediaPlayerState == mediaPLAYER_OPEN || m_mediaPlayerState == mediaPLAYER_PLAYING || m_mediaPlayerState == mediaPLAYER_PAUSE) { // 停止播放 m_mediaPlayer->stop(); m_mediaPlayerState = mediaPLAYER_STOP; } } void CAgoraMediaPlayer::OnDestroy() { // 销毁媒体播放器 CDialogEx::OnDestroy(); UnInitMediaPlayerKit(); }
参考信息
示例项目
声网提供了开源的示例项目供你参考,你可以前往下载或查看其中的源代码。
支持的格式
声网的媒体播放器支持下列格式及协议:
视频编码格式
- H.263、H.264、H.265、MPEG4、MPEG2、RMVB、Theora、VP3、VP8、AVS、WMV
音频编码格式
- WAV、MP2、MP3、AAC、OPUS、FLAC、Vorbis、AMR-NB、AMR-WB、WMA v1、WMA v2
容器格式
- WAV、FLAC、OGG、MOV、ASF、FLV、MP3、MP4、MPEG-TS、Matroska (MKV)、AVI、ASS、CONCAT、DTS、AVS
支持的协议
- HTTP、HTTPS、RTMP、HLS、RTP、RTSP
API 参考
本文介绍如何调用媒体播放器相关的 API 播放本地或在线媒体资源,或将媒体资源分享给声网频道内的远端用户。
前提条件
在进行操作之前,请确保你已经在项目中实现了基本的实时音视频功能。有关详细信息,请参考实现音视频互动。
实现方法
参考如下步骤,在你的项目中使用媒体播放器:
-
初始化
IRtcEngine后,创建一个IMediaPlayer对象。TypeScript // 创建并初始化引擎 let rtcEngine = createAgoraRtcEngine(); rtcEngine.initialize({ appId, }); // 创建媒体播放器对象 let mediaPlayer = rtcEngine.createMediaPlayer(); -
调用
registerPlayerSourceObserver方法注册播放观测器。TypeScript // 注册播放观测器 mediaPlayer.registerPlayerSourceObserver(this); -
根据你的需求,你可以注册以下媒体播放器观测器的回调:
onPlayerSourceStateChanged:报告播放器状态改变。onPositionChanged:报告当前媒体文件的播放进度。onPlayerEvent:报告播放器事件。
TypeScript const EventHandles = { // 报告播放器状态改变 onPlayerSourceStateChanged: (state, ec) { console.log(`state:${state}, ec:${ec}`); }; // 报告当前媒体文件的播放进度 onPositionChanged: (position) { console.log(`position:${position}`); }; // 报告播放器事件 onPlayerEvent: ( eventCode, elapsedTime, message ) { console.log( `eventCode:${eventCode}, elapsedTime:${elapsedTime}, message:${message}` ); }; }; // 添加主回调事件 rtcEngine.registerEventHandler(EventHandles); -
调用
open打开本地或在线媒体文件。TypeScript open = () => { const url = 'https://example/video.mov'; if (!url) { this.error("url is invalid"); } mediaPlayer.open(url, 0); }; -
调用
play播放媒体文件。TypeScript // 播放媒体文件 play = () => { const { position, duration } = this.state; if (position === duration && duration !== 0) { mediaPlayer.seek(0); } else { mediaPlayer.play(); } }; // 暂停播放媒体文件 pause = () => { mediaPlayer.pause(); }; // 恢复播放媒体文件 resume = () => { mediaPlayer.resume(); }; -
停止播放并释放资源。
TypeScript // 停止播放 mediaPlayer.stop(); // 销毁媒体播放器 rtcEngine.destroyMediaPlayer(this.player); // 取消注册播放观测器 rtcEngine.unregisterEventHandler(this);
参考信息
示例项目
声网提供了开源的实现媒体播放器示例项目供你参考,你可以前往下载或查看其中的源代码。
API 参考
媒体播放器是 RTC SDK 内置的一个播放器,支持播放多种格式的媒体资源。本文介绍如何调用媒体播放器相关的 API 播放本地或在线媒体资源,并将媒体资源分享给声网频道内的远端用户观看或收听。
前提条件
在进行操作之前,请确保你已经在项目中实现了基本的实时音视频功能。有关详细信息,请参考实现音视频互动。
实现方法
参考如下步骤,在你的项目中使用媒体播放器:
创建媒体播放器对象
初始化 IRtcEngine 后,调用 CreateMediaPlayer 创建一个 IMediaPlayer 对象。
注意
如果你需要创建多个媒体播放器对象,可以多次调用 CreateMediaPlayer。
MediaPlayer = RtcEngine.CreateMediaPlayer();
if (MediaPlayer == null)
{
this.Log.UpdateLog("CreateMediaPlayer failed!");
return;
}注册回调事件并实现回调
-
调用
IMediaPlayer类下的InitEventHandler方法添加媒体播放器的回调事件。C# MpkEventHandler handler = new MpkEventHandler(this); MediaPlayer.InitEventHandler(handler); this.Log.UpdateLog("playerId id: " + MediaPlayer.GetId()); -
根据你的需求,实现媒体播放器观测器的回调。
C# class MpkEventHandler : IMediaPlayerSourceObserver { // 报告播放器状态改变 public override void OnPlayerSourceStateChanged(MEDIA_PLAYER_STATE state, MEDIA_PLAYER_REASON reason) { } // 报告播放器的事件 public override void OnPlayerEvent(MEDIA_PLAYER_EVENT @event, Int64 elapsedTime, string message) { Debug.Log(string.Format("OnPlayerEvent state: {0}", @event)); } // 报告预加载媒体资源的事件 public override void OnPreloadEvent(string src, PLAYER_PRELOAD_EVENT @event) { Debug.Log(string.Format("OnPreloadEvent src: {0}, @event: {1}", src, @event)); } // 报告当前媒体资源的播放进度 public override void OnPositionChanged(long positionMs, long timestampMs) { } }
设置视频渲染窗口
如果你需要播放视频资源,在媒体资源打开后,设置视频渲染。当播放器停止播放时,销毁对应的视频视图。在渲染视图时,你可以通过 GetId 获取媒体播放器的 ID,并需要将 VIDEO_SOURCE_TYPE 设为 VIDEO_SOURCE_MEDIA_PLAYER。
// 报告播放器状态改变
public override void OnPlayerSourceStateChanged(MEDIA_PLAYER_STATE state, MEDIA_PLAYER_REASON reason)
{
Debug.Log(string.Format(
"OnPlayerSourceStateChanged state: {0}, ec: {1}, playId: {2}", state, reason, _sample.MediaPlayer.GetId()));
Debug.Log("OnPlayerSourceStateChanged");
if (state == MEDIA_PLAYER_STATE.PLAYER_STATE_OPEN_COMPLETED)
{
// 成功打开媒体资源后,创建一个视图用于显示媒体播放器的视频流
MakeVideoView((uint)_sample.MediaPlayer.GetId(), "", VIDEO_SOURCE_TYPE.VIDEO_SOURCE_MEDIA_PLAYER);
}
else if (state == MEDIA_PLAYER_STATE.PLAYER_STATE_STOPPED)
{
// 播放停止后,销毁视频视图
DestroyVideoView((uint)_sample.MediaPlayer.GetId());
}
}调用 SetForUser 设置视频显示,调用 SetEnable 开始视频渲染。
// 创建一个视频视图
static void MakeVideoView(uint uid, string channelId = "", VIDEO_SOURCE_TYPE videoSourceType = VIDEO_SOURCE_TYPE.VIDEO_SOURCE_CAMERA)
{
var go = GameObject.Find(uid.ToString());
if (!ReferenceEquals(go, null))
{
return;
}
// 创建一个新的 GameObject 用于渲染视频
var videoSurface = MakeImageSurface(uid.ToString());
if (ReferenceEquals(videoSurface, null)) return;
// 设置视频显示
videoSurface.SetForUser(uid, channelId, videoSourceType);
// 开始视频渲染
videoSurface.SetEnable(true);
// Texture 的宽高发生改变回调
videoSurface.OnTextureSizeModify += (int width, int height) =>
{
var transform = videoSurface.GetComponent<RectTransform>();
if (transform)
{
// 如果在 RawImage 中渲染,只需设置 RawImage 的大小
transform.sizeDelta = new Vector2(width / 2, height / 2);
transform.localScale = Vector3.one;
}
else
{
// 如果在 MeshRenderer 中渲染,只需设置 MeshRenderer 的本地大小
float scale = (float)height / (float)width;
videoSurface.transform.localScale = new Vector3(-1, 1, scale);
}
Debug.Log("OnTextureSizeModify: " + width + " " + height);
};
}
// 销毁视频视图
static void DestroyVideoView(uint uid)
{
var go = GameObject.Find(uid.ToString());
if (!ReferenceEquals(go, null))
{
Destroy(go);
}
}
// 创建一个新的视频视图,包含一个 RawImage 组件,用于显示视频
private static VideoSurface MakeImageSurface(string goName)
{
// 创建一个新的 GameObject
GameObject go = new GameObject();
go.name = goName;
// 添加 RawImage 组件,用于渲染视频
go.AddComponent<RawImage>();
go.AddComponent<UIElementDrag>();
var canvas = GameObject.Find("VideoCanvas");
if (canvas != null)
{
go.transform.parent = canvas.transform;
Debug.Log("add video view");
}
else
{
Debug.Log("Canvas is null video view");
}
// 设置 GameObject 的变换
go.transform.Rotate(0f, 0.0f, 180.0f);
go.transform.localPosition = Vector3.zero;
go.transform.localScale = new Vector3(4.5f, 3f, 1f);
// 添加 VideoSurface 组件
var videoSurface = go.AddComponent<VideoSurface>();
return videoSurface;
}
打开媒体资源
调用 Open 打开本地或在线媒体文件并设置起始播放位置。支持打开的媒体资源格式见支持的格式。
public void OnOpenButtonPress()
{
var ret = MediaPlayer.Open("Your File Path", 0);
Debug.Log("Open returns: " + ret);
}声网还提供 OpenWithMediaSource 方法打开媒体资源,同时可以进行播放设置,例如设置是否开启自动播放、实时缓存等功能。
发布媒体播放器的音视频流
调用 JoinChannel 加入频道时,在 ChannelMediaOptions 中进行如下设置:
- 设置用户角色为主播(
CLIENT_ROLE_BROADCASTER)。 - 将
autoSubscribeAudio和autoSubscribeVideo设为true,自动订阅所有音视频流。 - 将
publishMediaPlayerAudioTrack和publishMediaPlayerVideoTrack设为true,发布媒体播放器的音视频流。 - 将
publishMediaPlayerId设为你的媒体播放器的 ID。 - 将
enableAudioRecordingOrPlayout设为true,开启音频播放。
ChannelMediaOptions options = new ChannelMediaOptions();
// 自动订阅远端的音频流
options.autoSubscribeAudio.SetValue(true);
// 自动订阅远端的视频流
options.autoSubscribeVideo.SetValue(true);
options.publishCustomAudioTrack.SetValue(false);
options.publishCameraTrack.SetValue(false);
// 设置发布视频播放器的音频流
options.publishMediaPlayerAudioTrack.SetValue(true);
// 设置发布视频播放器的视频流
options.publishMediaPlayerVideoTrack.SetValue(true);
// 待发布的媒体播放器的 ID
options.publishMediaPlayerId.SetValue(MediaPlayer.GetId());
// 开启音频录制或播放
options.enableAudioRecordingOrPlayout.SetValue(true);
// 设置用户角色为主播
options.clientRoleType.SetValue(CLIENT_ROLE_TYPE.CLIENT_ROLE_BROADCASTER);
// 加入频道
var ret = RtcEngine.JoinChannel(_token, _channelName, 0, options);
this.Log.UpdateLog("RtcEngineController JoinChannel_MPK returns: " + ret);播放控制
本节介绍如何实现播放控制,包括暂停、恢复播放、停止播放等功能。
播放
调用 Play 方法播放本地或在线媒体资源。
注意
- 如果你通过
Open打开媒体资源,你需要在收到OnPlayerSourceStateChanged回调报告状态为PLAYER_STATE_OPEN_COMPLETED后再调用Play进行播放。 - 如果你通过
OpenWithMediaSource打开媒体资源,且autoPlay为true时,媒体资源打开后会自动播放,无需再额外调用Play方法。
public void OnPlayButtonPress()
{
var ret = MediaPlayer.Play();
Debug.Log("Play return" + ret);
}循环播放
如果你需要循环播放,可以调用 SetLoopCount 方法并通过 loopCount 参数设置循环播放的次数,默认为 0,表示不循环播放。如需无限循环播放,将该参数设为 -1。
public void OnPlayButtonPress()
{
if (this.IsLoop())
{
MediaPlayer.SetLoopCount(-1);
}
else
{
MediaPlayer.SetLoopCount(0);
}
var ret = MediaPlayer.Play();
this.Log.UpdateLog("Play return" + ret);
}定位指定位置播放
如果你需要定位到媒体资源的指定位置再播放,可以调用 Seek 方法定位到指定位置。
注意
- 请确保在成功打开媒体文件后(即收到
OnPlayerSourceStateChanged回调报告状态为PLAYER_STATE_OPEN_COMPLETED)再调用Seek。成功调用后,媒体播放器会自动从指定位置开始播放,并报告状态为PLAYER_STATE_PLAYING。 - 如果你在暂停播放的情况下调用
Seek,成功调用后,媒体资源仍然会是暂停播放的状态。如需播放,请调用Resume或Play。
设置播放速度
调用 SetPlaybackSpeed 方法来设置当前媒体文件的播放速度。
public void OnSetPlaybackSpeedButtonPress()
{
var ret = MediaPlayer.SetPlaybackSpeed(2);
this.Log.UpdateLog("SetPlaybackSpeed return" + ret);
}暂停播放
调用 Pause 方法暂停当前播放。
public void OnPauseButtonPress()
{
var ret = MediaPlayer.Pause();
this.Log.UpdateLog("Pause return" + ret);
}恢复播放
暂停播放后,如需恢复播放,调用 Resume 方法。
public void OnResumeButtonPress()
{
var ret = MediaPlayer.Resume()
this.Log.UpdateLog("Resume returns: " + ret);
}停止播放
调用 Stop 方法停止播放。停止播放后,如果你需要再次播放,需要重新打开该媒体资源。
public void OnStopButtonPress()
{
var ret = MediaPlayer.Stop();
this.Log.UpdateLog("Stop return" + ret);
}调整音量
如果你需要调整媒体播放器本地播放的音量,调用 AdjustPlayoutVolume。如果要调整所播放的媒体资源发布到远端的音量,调用 AdjustPublishSignalVolume。
var ret = MediaPlayer.AdjustPlayoutVolume(30);
this.Log.UpdateLog("AdjustPlayoutVolume return" + ret);
ret = MediaPlayer.AdjustPublishSignalVolume(50);
this.Log.UpdateLog("AdjustPublishSignalVolume return" + ret);预加载媒体资源
如果你需要连续播放多个不同的媒体资源,可以预先加载待播放的媒体资源以保证资源切换时的观众体验。
-
调用
PreloadSrc预加载媒体资源。如需加载多个资源,你可以多次调用该方法。预加载的相关事件可以通过监听OnPreloadEvent回调得知。C# public void OnPreloadSrcButtonClick() { var nRet = MediaPlayer.PreloadSrc(PRELOAD_URL, 0); this.Log.UpdateLog("PreloadSrc: " + nRet); } -
调用
PlayPreloadedSrc播放预加载的媒体资源。调用该方法后,如果你收到OnPlayerSourceStateChanged回调报告状态PLAYER_STATE_PLAYING,则表示播放成功。C# public void OnPlayPreloadButtonClick() { var nRet = MediaPlayer.PlayPreloadedSrc(PRELOAD_URL); this.Log.UpdateLog("PlayPreloadedSrc: " + nRet); } -
如果不再需要已加载的媒体资源,可以调用
UnloadSrc释放预加载的资源。C# var nRet = MediaPlayer.UnloadSrc(PRELOAD_URL); this.Log.UpdateLog("UnloadSrc: " + nRet);
离开频道
参考下列步骤离开频道:
- 调用
DestroyMediaPlayer销毁媒体播放器对象。 - 调用
InitEventHandler取消注册播放器事件观测器。 - 调用
LeaveChannel离开频道。 - 调用
Dispose销毁IRtcEngine对象并释放 SDK 使用的资源。
public void OnLeaveChannelButtonPress()
{
if (RtcEngine == null) return;
// 销毁媒体播放器对象
if (MediaPlayer != null) RtcEngine.DestroyMediaPlayer(MediaPlayer);
// 取消注册播放器事件观测器
RtcEngine.InitEventHandler(null);
// 离开频道
RtcEngine.LeaveChannel();
// 销毁引擎并释放资源
RtcEngine.Dispose();
RtcEngine = null;
MediaPlayer = null;
}参考信息
示例项目
声网提供了开源的音视频互动示例项目供你参考,你可以前往下载或查看其中的源代码。
支持的格式
声网的媒体播放器支持下列格式及协议:
视频编码格式
- H.263、H.264、H.265、MPEG4、MPEG2、RMVB、Theora、VP3、VP8、AVS、WMV
音频编码格式
- WAV、MP2、MP3、AAC、OPUS、FLAC、Vorbis、AMR-NB、AMR-WB、WMA v1、WMA v2
容器格式
- WAV、FLAC、OGG、MOV、ASF、FLV、MP3、MP4、MPEG-TS、Matroska (MKV)、AVI、ASS、CONCAT、DTS、AVS
支持的协议
- HTTP、HTTPS、RTMP、HLS、RTP、RTSP
API 参考
本文介绍如何调用媒体播放器相关的 API 播放本地或在线媒体资源,或将媒体资源分享给声网频道内的远端用户。
前提条件
在进行操作之前,请确保你已经在项目中实现了基本的实时音视频功能。有关详细信息,请参考实现音视频互动。
实现方法
参考如下步骤,在你的项目中使用媒体播放器:
-
初始化
IRtcEngine后,创建一个IMediaPlayer对象。TypeScript // 创建并初始化引擎 let rtcEngine = createAgoraRtcEngine(); rtcEngine.initialize({ appId, }); // 创建媒体播放器对象 let mediaPlayer = rtcEngine.createMediaPlayer(); -
调用
registerPlayerSourceObserver方法注册播放观测器。TypeScript // 注册播放观测器 mediaPlayer.registerPlayerSourceObserver(this); -
根据你的需求,你可以注册以下媒体播放器观测器的回调:
onPlayerSourceStateChanged:报告播放器状态改变。onPositionChanged:报告当前媒体文件的播放进度。onPlayerEvent:报告播放器事件。
TypeScript const EventHandles = { // 报告播放器状态改变 onPlayerSourceStateChanged: (state, ec) { console.log(`state:${state}, ec:${ec}`); }; // 报告当前媒体文件的播放进度 onPositionChanged: (position) { console.log(`position:${position}`); }; // 报告播放器事件 onPlayerEvent: ( eventCode, elapsedTime, message ) { console.log( `eventCode:${eventCode}, elapsedTime:${elapsedTime}, message:${message}` ); }; }; // 添加主回调事件 rtcEngine.registerEventHandler(EventHandles); -
调用
open打开本地或在线媒体文件。TypeScript open = () => { const url = 'https://example/video.mov'; if (!url) { this.error("url is invalid"); } mediaPlayer.open(url, 0); }; -
调用
play播放媒体文件。TypeScript // 播放媒体文件 play = () => { const { position, duration } = this.state; if (position === duration && duration !== 0) { mediaPlayer.seek(0); } else { mediaPlayer.play(); } }; // 暂停播放媒体文件 pause = () => { mediaPlayer.pause(); }; // 恢复播放媒体文件 resume = () => { mediaPlayer.resume(); }; -
停止播放并释放资源。
TypeScript // 停止播放 mediaPlayer.stop(); // 销毁媒体播放器 rtcEngine.destroyMediaPlayer(this.player); // 取消注册播放观测器 rtcEngine.unregisterEventHandler(this);
参考信息
示例项目
声网提供了开源的实现媒体播放器示例项目供你参考,你可以前往下载或查看其中的源代码。