Unity 2022.3.11f1播放AWS S3预签名URL视频报错求助
问题场景
用Unity的VideoPlayer播放AWS S3预签名URL时,触发以下错误:
AVFoundationVideoMedia error while reading 'url' Context: AVFoundationVideoMedia::OpenForRead found no video tracks
Error details:
VideoPlayer cannot play url: 'url' Cannot read file.
Unity 2021.3.8f1中正常运行,升级到2022.3.11f1后出现问题,要求流式播放,不能先下载再播放。已知Unity 2022版本的VideoPlayer对URL后缀有校验要求,但S3预签名URL格式为https://~?X-Amz-Expires=600&X-Amz-Security-Token=~,不带.mp4后缀。
获取S3预签名URL的代码如下:
public async Task<string> GetObjectUrl(AWSCredentials credentials, string keyName) { using (var client = new AmazonS3Client(credentials, RegionEndpoint.APNortheast2)) { try { GetPreSignedUrlRequest request = new GetPreSignedUrlRequest { BucketName = BUCKET_NAME, Key = keyName, Expires = DateTime.Now.AddMinutes(10) }; return client.GetPreSignedURL(request); } catch (AmazonS3Exception e) { // 如果桶或对象不存在 Debug.Log($"Error: '{e.Message}'"); return null; } } }
解决方法
方法1:给预签名URL添加锚点后缀
在S3返回的预签名URL末尾拼接#.mp4,锚点后的内容不会发送到S3服务器,不影响签名验证,但能让Unity的AVFoundation后端识别为MP4格式。修改代码如下:
var signedUrl = client.GetPreSignedURL(request); // 拼接锚点后缀,让VideoPlayer识别文件类型 return $"{signedUrl}#.mp4";
方法2:强制指定响应的Content-Type
在生成预签名URL时,添加ResponseContentType参数,让S3返回的响应头包含video/mp4,Unity会根据这个头识别视频类型,不用依赖URL后缀:
GetPreSignedUrlRequest request = new GetPreSignedUrlRequest { BucketName = BUCKET_NAME, Key = keyName, Expires = DateTime.Now.AddMinutes(10), // 强制返回video/mp4类型 ResponseContentType = "video/mp4" };
也可以直接在S3控制台修改视频对象的元数据,将Content-Type设置为video/mp4,这是更规范的做法。
方法3:添加响应头指定文件名后缀
通过ResponseHeaderOverrides设置Content-Disposition,让URL附带正确的文件名后缀,同时不改变S3上的实际对象:
GetPreSignedUrlRequest request = new GetPreSignedUrlRequest { BucketName = BUCKET_NAME, Key = keyName, Expires = DateTime.Now.AddMinutes(10), ResponseHeaderOverrides = new ResponseHeaderOverrides { // 若keyName本身带.mp4,直接用Path.GetFileName(keyName)即可 ContentDisposition = $"attachment; filename=\"{Path.GetFileNameWithoutExtension(keyName)}.mp4\"" } };
验证顺序
优先尝试方法2(配置Content-Type),这是符合HTTP规范的解决方案;如果无效,再试方法1(锚点后缀),代码改动最小;方法3适合需要浏览器下载时显示正确文件名的场景。
内容的提问来源于stack exchange,提问作者MayQuartet

