swift - 带视频的 SCNPlane 在模拟器上播放,但在设备上不播放
问题描述
我有一个要渲染到 SCNPlane 上的视频层。它适用于模拟器,但不适用于设备。
这是一个视觉效果:
这是代码:
//DISPLAY PLANE
SCNPlane * displayPlane = [SCNPlane planeWithWidth:displayWidth height:displayHeight];
displayPlane.cornerRadius = cornerRadius;
SCNNode * displayNode = [SCNNode nodeWithGeometry:displayPlane];
[scene.rootNode addChildNode:displayNode];
//apply material
SCNMaterial * displayMaterial = [SCNMaterial material];
displayMaterial.diffuse.contents = [[UIColor greenColor] colorWithAlphaComponent:1.0f];
[displayNode.geometry setMaterials:@[displayMaterial]];
//move to front + position for rim
displayNode.position = SCNVector3Make(0, rimTop - 0.08, /*0.2*/ 1);
//create video item
NSBundle * bundle = [NSBundle mainBundle];
NSString * path = [bundle pathForResource:@"tv_preview" ofType:@"mp4"];
NSURL * url = [NSURL fileURLWithPath:path];
AVAsset * asset = [AVAsset assetWithURL:url];
AVPlayerItem * item = [AVPlayerItem playerItemWithAsset:asset];
queue = [AVQueuePlayer playerWithPlayerItem:item];
looper = [AVPlayerLooper playerLooperWithPlayer:queue templateItem:item];
queue.muted = true;
layer = [AVPlayerLayer playerLayerWithPlayer:queue];
layer.frame = CGRectMake(0, 0, w, h);
layer.videoGravity = AVLayerVideoGravityResizeAspectFill;
displayMaterial.diffuse.contents = layer;
displayMaterial.doubleSided = true;
[queue play];
//[self.view.layer addSublayer:layer];
我可以确认实际平面存在(如果 avplayerlayer 未应用于它,则在上图中显示为绿色) - 上面的第一张图片。如果视频层直接添加到父视图层(上面的底线),它运行良好 - 上面的最终图像。我认为这可能是文件系统问题,但后来我想(?)视频不会在最终图像中播放。
编辑:设置队列(AVPlayer)直接在模拟器上工作,虽然丑得要命,并且在设备上崩溃,并带有以下错误日志:
Error: Could not get pixel buffer (CVPixelBufferRef)
validateFunctionArguments:3797: failed assertion `Fragment Function(commonprofile_frag): incorrect type of texture (MTLTextureType2D) bound at texture binding at index 4 (expect MTLTextureTypeCube) for u_radianceTexture[0].'
解决方案
我认为我的解决方案会适合您 - 唯一的问题是这里需要进行一些小改动:
#import <SceneKit/SceneKit.h>
#import <AVKit/AVKit.h>
#import <SpriteKit/SpriteKit.h>
@interface ViewController: UIViewController
@end
它适用于模拟器(在 Xcode 13.2.1 中)和设备(我在带有 iOS 15.3 的 iPhone X 上运行它)。我使用了 640x360 H.265 视频。这里唯一的问题 - 视频循环是口吃......
#import "ViewController.h"
@implementation ViewController
AVQueuePlayer *queue;
AVPlayerLooper *looper;
SKVideoNode *videoNode;
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
SCNView *sceneView = (SCNView *)self.view;
sceneView.backgroundColor = [UIColor blackColor];
sceneView.autoenablesDefaultLighting = YES;
sceneView.allowsCameraControl = YES;
sceneView.playing = YES;
sceneView.loops = YES;
SCNScene *scene = [SCNScene scene];
sceneView.scene = scene;
// Display
SCNPlane *displayPlane = [SCNPlane planeWithWidth:1.6 height:0.9];
SCNNode *displayNode = [SCNNode nodeWithGeometry:displayPlane];
SCNMaterial *displayMaterial = [SCNMaterial material];
displayMaterial.lightingModelName = SCNLightingModelConstant;
displayMaterial.doubleSided = YES;
// Video
NSBundle *bundle = [NSBundle mainBundle];
NSString *path = [bundle pathForResource:@"art.scnassets/hevc"
ofType:@"mp4"];
NSURL *url = [NSURL fileURLWithPath:path];
AVAsset *asset = [AVAsset assetWithURL:url];
AVPlayerItem *item = [AVPlayerItem playerItemWithAsset:asset];
queue = [AVQueuePlayer playerWithPlayerItem:item];
queue.muted = NO;
looper = [AVPlayerLooper playerLooperWithPlayer:queue templateItem:item];
// SpriteKit video node
videoNode = [SKVideoNode videoNodeWithAVPlayer:queue];
videoNode.zRotation = -M_PI;
videoNode.xScale = -1;
SKScene *skScene = [SKScene sceneWithSize: CGSizeMake(
displayPlane.width * 1000,
displayPlane.height * 1000)];
videoNode.position = CGPointMake(skScene.size.width / 2,
skScene.size.height / 2);
videoNode.size = skScene.size;
[videoNode play];
[skScene addChild:videoNode];
displayMaterial.diffuse.contents = skScene;
[displayNode.geometry setMaterials:@[displayMaterial]];
[scene.rootNode addChildNode:displayNode];
}
@end
推荐阅读
- android - 如何防止约束视图中的 textView 离开屏幕
- angular - 如何解决角度示意图导航隐藏侧边栏的问题?
- javascript - 关闭表格折叠行
- c++ - 我需要将我的数组样式的邻接矩阵转换为矢量样式(使其看起来更好)
- c++ - 在 Linux 上使用 CMake 时,如何告诉 PVS-Studio 忽略第三方库中的所有文件
- androidx - Android - 导入 ViewPager2 库时程序类型已经存在 com.transition.R
- javascript - Modify properties of objects in array, based on string array
- javascript - 尝试将对象中的每个数字/值放入字符串数组
- java - 当我们将一个类变量分配给另一个类变量时,我们到底在做什么
- javascript - 为什么我不能读取我在 POST 中收到的参数?