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

Swift 5中如何通过Google Drive API在AVPlayer播放受限音频文件

解决Google Drive受限音频文件的播放问题

好问题!要播放Google Drive中「受限」权限的音频文件,核心是让AVPlayer的资源请求带上有效的OAuth 2.0授权凭证——毕竟受限文件需要验证用户身份,而你已经通过API拿到了用户的授权,只需要把凭证注入到播放请求里就行。

实现思路

AVPlayer本身不支持直接给请求添加自定义HTTP头(比如Authorization),所以我们需要用AVAssetResourceLoaderDelegate来拦截AVPlayer的资源加载请求,手动添加上授权Token,再转发给Google Drive的媒体接口。

具体代码实现

1. 自定义资源加载代理类

这个类负责拦截AVPlayer的请求,添加授权头后再发起实际的网络请求:

import AVKit

class DriveAudioResourceLoaderDelegate: NSObject, AVAssetResourceLoaderDelegate {
    private let authToken: String
    
    init(authToken: String) {
        self.authToken = authToken
        super.init()
    }
    
    func resourceLoader(_ resourceLoader: AVAssetResourceLoader, shouldWaitForLoadingOfRequestedResource loadingRequest: AVAssetResourceLoadingRequest) -> Bool {
        guard let requestUrl = loadingRequest.request.url else {
            let error = NSError(domain: "DriveAudioError", code: -1, userInfo: [NSLocalizedDescriptionKey: "无效的请求URL"])
            loadingRequest.finishLoading(with: error)
            return false
        }
        
        // 构造带授权头的请求
        var authorizedRequest = URLRequest(url: requestUrl)
        authorizedRequest.addValue("Bearer \(authToken)", forHTTPHeaderField: "Authorization")
        
        // 发起网络请求获取音频数据
        let task = URLSession.shared.dataTask(with: authorizedRequest) { data, response, error in
            defer {
                loadingRequest.finishLoading()
            }
            
            if let error = error {
                loadingRequest.finishLoading(with: error)
                return
            }
            
            guard let httpResponse = response as? HTTPURLResponse, let data = data else {
                let error = NSError(domain: "DriveAudioError", code: -2, userInfo: [NSLocalizedDescriptionKey: "未获取到有效数据或响应"])
                loadingRequest.finishLoading(with: error)
                return
            }
            
            // 把响应信息和数据返回给AVPlayer
            loadingRequest.contentInformationRequest?.contentType = httpResponse.mimeType
            loadingRequest.contentInformationRequest?.contentLength = httpResponse.expectedContentLength
            loadingRequest.dataRequest?.respond(with: data)
        }
        
        task.resume()
        return true
    }
}

2. 修改播放方法

在你的ViewController中,使用上面的代理类来处理受限文件的播放:

private func playRestrictedTrack(fileId: String, authToken: String) {
    // 构造Google Drive媒体文件的请求URL(用files.get接口+alt=media参数获取原始媒体数据)
    guard let mediaUrl = URL(string: "https://www.googleapis.com/drive/v3/files/\(fileId)?alt=media") else {
        print("无效的文件ID")
        return
    }
    
    // 创建带资源加载代理的AVURLAsset
    let asset = AVURLAsset(url: mediaUrl)
    let resourceDelegate = DriveAudioResourceLoaderDelegate(authToken: authToken)
    asset.resourceLoader.setDelegate(resourceDelegate, queue: DispatchQueue.global())
    
    // 初始化播放器并开始播放
    let playerItem = AVPlayerItem(asset: asset)
    player = AVPlayer(playerItem: playerItem)
    player.play()
}

关键注意事项

  • 权限范围:确保你的OAuth 2.0请求申请了https://www.googleapis.com/auth/drive.readonly权限(足够访问用户的受限文件),不需要更宽泛的权限。
  • Token过期处理:OAuth Token会过期,你需要监听Token的有效期,在过期前完成刷新,避免播放时出现授权失败。
  • 错误处理:代码里的错误处理可以根据你的App需求优化,比如弹出提示告知用户授权失效或网络异常。
  • 流式播放:这个方案支持流式播放,不需要下载完整音频文件,节省用户流量和设备内存。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.09 17:07:42