You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

WPF中MediaElement播放器如何携带Bearer Token访问SharePoint视频API

在WPF中使用带令牌验证的SharePoint Video REST API视频源

WPF的MediaElement控件本身没法直接在URI请求里附加Authorization令牌,不过我们可以通过两种常见方式绕开这个限制,实现播放受令牌保护的SharePoint视频:


方法一:临时文件中转(简单易实现)

如果视频文件不大,最省心的方式是先通过带令牌的请求把视频下载到临时文件,再让MediaElement播放这个临时文件,播放完成后自动清理。

代码示例

private async void LoadSharePointVideo()
{
    // 替换成你的SharePoint视频API地址和有效令牌
    string videoApiUrl = "https://your-sharepoint-site/_api/videos/getbyid('video-id')/content";
    string accessToken = "your-bearer-token-here";

    // 创建带格式后缀的临时文件,确保MediaElement能识别
    string tempVideoPath = Path.Combine(Path.GetTempPath(), $"{Guid.NewGuid()}.mp4");

    try
    {
        // 用HttpClient发送带令牌的请求,获取视频流
        using (var httpClient = new HttpClient())
        {
            httpClient.DefaultRequestHeaders.Authorization = 
                new AuthenticationHeaderValue("Bearer", accessToken);
            
            using (var videoStream = await httpClient.GetStreamAsync(videoApiUrl))
            using (var fileStream = new FileStream(tempVideoPath, FileMode.Create, FileAccess.Write))
            {
                await videoStream.CopyToAsync(fileStream);
            }
        }

        // 播放临时文件
        mediaElement.Source = new Uri(tempVideoPath);
        mediaElement.Play();

        // 播放结束后删除临时文件
        mediaElement.MediaEnded += (sender, e) =>
        {
            if (File.Exists(tempVideoPath))
            {
                try { File.Delete(tempVideoPath); }
                catch { /* 忽略删除错误,比如文件被占用 */ }
            }
        };
    }
    catch (Exception ex)
    {
        // 处理请求或播放错误,比如令牌过期、网络问题
        MessageBox.Show($"加载视频失败:{ex.Message}");
        if (File.Exists(tempVideoPath)) File.Delete(tempVideoPath);
    }
}

方法二:流式播放(无需下载完整文件)

如果视频文件较大,不想等待完整下载,可以通过自定义MediaStreamSource直接处理从API获取的流,实现边下边播。这种方式需要解析视频的媒体元数据(比如MP4的轨道信息),复杂度稍高。

核心思路

  1. 用HttpClient带令牌请求视频流;
  2. 解析视频的媒体信息(如视频/音频轨道编码、分辨率、帧率);
  3. 实现MediaStreamSource的抽象方法,将流中的媒体样本分发给MediaElement。

简化代码示例(需配合MP4解析逻辑)

首先实现自定义MediaStreamSource(这里假设你用第三方库或自己实现了MP4解析):

public class Mp4MediaStreamSource : MediaStreamSource
{
    private readonly Stream _videoStream;
    private readonly IMp4Parser _mp4Parser; // 自定义或第三方MP4解析器

    public Mp4MediaStreamSource(Stream videoStream)
    {
        _videoStream = videoStream;
        _mp4Parser = new Mp4Parser(videoStream); // 初始化解析器
    }

    protected override void OpenMediaAsync()
    {
        // 解析视频元数据,生成媒体描述
        var mediaInfo = _mp4Parser.ParseMediaInfo();
        var streamDescriptions = new List<MediaStreamDescription>();

        if (mediaInfo.VideoTrack != null)
        {
            streamDescriptions.Add(new MediaStreamDescription(MediaStreamType.Video, mediaInfo.VideoTrack));
        }
        if (mediaInfo.AudioTrack != null)
        {
            streamDescriptions.Add(new MediaStreamDescription(MediaStreamType.Audio, mediaInfo.AudioTrack));
        }

        ReportOpenMediaCompleted(mediaInfo.MediaAttributes, streamDescriptions);
    }

    protected override void GetSampleAsync(MediaStreamType streamType)
    {
        // 获取下一个媒体样本并返回给MediaElement
        var sample = _mp4Parser.GetNextSample(streamType);
        if (sample != null)
        {
            ReportGetSampleCompleted(new MediaStreamSample(
                sample.StreamDescription,
                sample.DataStream,
                sample.Offset,
                sample.Length,
                sample.Timestamp,
                sample.Attributes));
        }
        else
        {
            ReportGetSampleCompleted(null); // 播放结束
        }
    }

    // 重写其他必要方法:CloseMedia、SeekAsync等
    protected override void CloseMedia() => _videoStream?.Dispose();

    protected override void SeekAsync(long seekToTime)
    {
        _mp4Parser.SeekToTimestamp(seekToTime);
        ReportSeekCompleted(seekToTime);
    }

    protected override void SwitchMediaStreamAsync(MediaStreamDescription streamDescription)
    {
        ReportSwitchMediaStreamCompleted(streamDescription);
    }
}

然后在WPF中使用:

private async void LoadVideoStream()
{
    string videoApiUrl = "https://your-sharepoint-site/_api/videos/getbyid('video-id')/content";
    string accessToken = "your-bearer-token-here";

    try
    {
        using (var httpClient = new HttpClient())
        {
            httpClient.DefaultRequestHeaders.Authorization = 
                new AuthenticationHeaderValue("Bearer", accessToken);
            
            var videoStream = await httpClient.GetStreamAsync(videoApiUrl);
            var mediaSource = new Mp4MediaStreamSource(videoStream);
            
            mediaElement.SetSource(mediaSource);
            mediaElement.Play();
        }
    }
    catch (Exception ex)
    {
        MessageBox.Show($"流式加载失败:{ex.Message}");
    }
}

注意事项

  • 令牌有效期:播放过程中如果令牌过期,需要重新获取并刷新流请求;
  • 资源清理:确保流和临时文件在使用后被正确释放,避免内存泄漏;
  • 权限验证:确认你的Bearer令牌拥有访问目标SharePoint视频的权限(如Files.Read或视频专属权限)。

内容的提问来源于stack exchange,提问作者Nicolas

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 08:27:32