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

如何确保AR App中同一时间仅播放一个视频?

解决方案:AR图像锚点视频互斥播放

核心问题

每次扫描新图像时,旧的视频节点未被停止或销毁,导致多个视频同时播放。需要在播放新视频前,终止所有已存在的视频播放实例。

具体实现步骤

1. 添加视频节点跟踪属性

在你的AR视图控制器类中,添加数组记录当前活跃的视频节点:

var activeVideoNodes: [SKVideoNode] = []

2. 重构视频节点创建逻辑

将重复的视频节点创建代码抽成通用方法,减少冗余:

private func createVideoNode(for videoFileName: String, with imageAnchor: ARImageAnchor) -> SCNNode {
    // 创建视频节点并播放
    let videoNode = SKVideoNode(fileNamed: videoFileName)
    videoNode.play()
    activeVideoNodes.append(videoNode)
    
    // 配置视频场景
    let videoScene = SKScene(size: CGSize(width: 480, height: 360))
    videoNode.position = CGPoint(x: videoScene.size.width / 2, y: videoScene.size.height / 2)
    videoNode.yScale = -1.0
    videoScene.addChild(videoNode)
    
    // 创建匹配图像尺寸的平面节点
    let plane = SCNPlane(width: imageAnchor.referenceImage.physicalSize.width, 
                         height: imageAnchor.referenceImage.physicalSize.height)
    plane.firstMaterial?.diffuse.contents = videoScene
    
    let planeNode = SCNNode(geometry: plane)
    planeNode.eulerAngles.x = -.pi / 2
    
    return planeNode
}

3. 修改锚点节点创建方法

生成新锚点节点前,先停止并清理所有旧视频:

func renderer(_ renderer: SCNSceneRenderer, nodeFor anchor: ARAnchor) -> SCNNode? {
    let node = SCNNode()
    
    guard let imageAnchor = anchor as? ARImageAnchor else { return node }
    
    // 停止所有活跃视频并清理
    activeVideoNodes.forEach { videoNode in
        videoNode.pause()
        videoNode.removeFromParent()
    }
    activeVideoNodes.removeAll()
    
    // 根据图像名称创建对应视频节点
    switch imageAnchor.referenceImage.name {
    case "harrypotter":
        let videoPlane = createVideoNode(for: "harrypotter.mp4", with: imageAnchor)
        node.addChildNode(videoPlane)
    case "deatheater":
        let videoPlane = createVideoNode(for: "deatheater.mp4", with: imageAnchor)
        node.addChildNode(videoPlane)
    default:
        break
    }
    
    return node
}

4. 处理图像消失场景(可选)

当图像锚点从场景中移除时,同步停止对应视频:

func renderer(_ renderer: SCNSceneRenderer, didRemove node: SCNNode, for anchor: ARAnchor) {
    node.enumerateChildNodes { childNode, _ in
        guard let plane = childNode.geometry as? SCNPlane,
              let videoScene = plane.firstMaterial?.diffuse.contents as? SKScene else { return }
        
        videoScene.enumerateChildNodes { skNode, _ in
            guard let videoNode = skNode as? SKVideoNode else { return }
            videoNode.pause()
            videoNode.removeFromParent()
            if let index = activeVideoNodes.firstIndex(of: videoNode) {
                activeVideoNodes.remove(at: index)
            }
        }
    }
}

原理说明

通过activeVideoNodes数组跟踪所有正在播放的视频实例,每次创建新视频前先终止旧实例的播放并从父节点移除,确保同一时间只有一个视频在播放。同时重构代码减少重复逻辑,提升可维护性。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 12:45:34