jjzjj

swift - 确定 SceneKit 中 SKVideoNode 的视频大小/纵横比

coder 2024-01-23 原文

如何从 AVPlayer 获取视频的视频大小以设置我的节点的几何大小?

例如,我有一个具有宽度和高度的 SCNPlane

let planeGeo = SCNPlane(width: 5, height: 5)

所以现在我实例化我的视频播放器

let videoURL = NSURL(string: someURL)
let player = AVPlayer(URL: videoURL!)

和我的 SKVideoNode

let spriteKitScene = SKScene(size: CGSize(width: 1920, height: 1080))
spriteKitScene.scaleMode = .AspectFit

videoSpriteKitNode = SKVideoNode(AVPlayer: player)
videoSpriteKitNode.anchorPoint = CGPointMake(0,0)
videoSpriteKitNode.size.width = spriteKitScene.size.width
videoSpriteKitNode.size.height = spriteKitScene.size.height

spriteKitScene.addChild(videoSpriteKitNode)

planeGeo!.firstMaterial.diffuse.contents = spriteKitScene
videoSpriteKitNode.play()

所以现在我想要视频大小来将我的平面大小调整为正确的纵横比。我已经摆弄过 AVLPlayerLayer 但这总是给我 0

let avLayer = AVPlayerLayer(player: player)
print(avLayer.videoRect.width) //0
print(avLayer.videoRect.height) //0

我也试过,但效果不佳

let avLayer = AVPlayerLayer(player: player)
let layer = avLayer.sublayers![0]
let transformedBounds = CGRectApplyAffineTransform(layer.bounds, CATransform3DGetAffineTransform(layer.sublayerTransform))
print(transformedBounds.width) //0
print(transformedBounds.height) //0

最佳答案

好的,我明白了,KVO 是正确的选择。在viewDidLoad中添加:

player.currentItem?.addObserver(self, forKeyPath: "presentationSize", options: .New, context: nil)

在初始化中:

player.currentItem?.removeObserver(self, forKeyPath: "presentationSize")

然后添加:

override func observeValueForKeyPath(keyPath: String?, ofObject object: AnyObject?, change: [String : AnyObject]?, context: UnsafeMutablePointer<Void>) {
    
    if keyPath == "presentationSize" {
        if let item = object as? AVPlayerItem {
            let size = item.presentationSize
            let width = size.width
            let height = size.height

            //Set size of geometry here
        }
    }
}

2022语法的典型代码:

var py: AVPlayer?
private var pyContext = 0
...

guard let url = URL(string: "https:// .. /test.m4v") else { return }
py = AVPlayer(url: url)
someNode.geometry?.firstMaterial?.diffuse.contents = py

py?.currentItem?.addObserver(self,
   forKeyPath: "presentationSize",
   context: &pyContext)    
...

override func observeValue(forKeyPath keyPath: String?,
                           of object: Any?,
                           change: [NSKeyValueChangeKey : Any]?,
                           context: UnsafeMutableRawPointer?) {

    if context == &py1Context && keyPath == "presentationSize" {
        print("Found it ...")

        guard let item = object as AVPlayerItem else { return }

        let ps = item.presentationSize
        let aspect: Float = Float(ps.width) / Float(ps.height)
        someNode.geometry?.firstMaterial?
           .diffuse.contentsTransform =
           SCNMatrix4MakeScale( .. , .. , 1)
    }
}

附录。计算正确的缩放比例很棘手

不幸的是,任何时候您处理视频时,如果流媒体内容的确切大小并不总是相同,那么塑造视频就是一个巨大的痛苦。当然你有很多考虑因素,比如是否有信箱等等。在一些简单的情况下计算看起来像这样:

// 1. You nave finally received the info on the video from the HLS stream:

let ps = item.presentationSize
let spect: Float = Float(ps.width) / Float(ps.height)

// 2. Over in your 3D code, you need to know the current facts on the mesh:

let planeW = ... width of your mesh
let planeH = ... height of your mesh
let planeAspect = planeW / planeH

您可能正在使用 Apple 提供的简单的平面方形网格,例如

var simplePlane = SCNPlane()
simplePlane.width = 2.783
simplePlane.height = 1.8723

不管怎样,您都需要网格的 w/h。然后,

// 3. In many (not all) cases, the solution is:

let final = vidAspect / planeAspect
print("we'll try this: \(final)")
yourNode.geometry?
  .firstMaterial?.diffuse
  .contentsTransform = SCNMatrix4MakeScale(1.0, final, 1.0)

关于swift - 确定 SceneKit 中 SKVideoNode 的视频大小/纵横比,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34928396/

有关swift - 确定 SceneKit 中 SKVideoNode 的视频大小/纵横比的更多相关文章

  1. ruby-on-rails - 在 Rails 中将文件大小字符串转换为等效千字节 - 2

    我的目标是转换表单输入,例如“100兆字节”或“1GB”,并将其转换为我可以存储在数据库中的文件大小(以千字节为单位)。目前,我有这个:defquota_convert@regex=/([0-9]+)(.*)s/@sizes=%w{kilobytemegabytegigabyte}m=self.quota.match(@regex)if@sizes.include?m[2]eval("self.quota=#{m[1]}.#{m[2]}")endend这有效,但前提是输入是倍数(“gigabytes”,而不是“gigabyte”)并且由于使用了eval看起来疯狂不安全。所以,功能正常,

  2. ruby - 即时确定方法的可见性 - 2

    我正在编写一个方法,它将在一个类中定义一个实例方法;类似于attr_accessor:classFoocustom_method(:foo)end我通过将custom_method函数添加到Module模块并使用define_method定义方法来实现它,效果很好。但我无法弄清楚如何考虑类(class)的可见性属性。例如,在下面的类中classFoocustom_method(:foo)privatecustom_method(:bar)end第一个生成的方法(foo)必须是公共(public)的,第二个(bar)必须是私有(private)的。我怎么做?或者,如何找到调用我的cust

  3. ruby - 寻找通过阅读代码确定编程语言的ruby gem? - 2

    几个月前,我读了一篇关于ruby​​gem的博客文章,它可以通过阅读代码本身来确定编程语言。对于我的生活,我不记得博客或gem的名称。谷歌搜索“ruby编程语言猜测”及其变体也无济于事。有人碰巧知道相关gem的名称吗? 最佳答案 是这个吗:http://github.com/chrislo/sourceclassifier/tree/master 关于ruby-寻找通过阅读代码确定编程语言的rubygem?,我们在StackOverflow上找到一个类似的问题:

  4. 动漫制作技巧如何制作动漫视频 - 2

    动漫制作技巧是很多新人想了解的问题,今天小编就来解答与大家分享一下动漫制作流程,为了帮助有兴趣的同学理解,大多数人会选择动漫培训机构,那么今天小编就带大家来看看动漫制作要掌握哪些技巧?一、动漫作品首先完成草图设计和原型制作。设计草图要有目的、有对象、有步骤、要形象、要简单、符合实际。设计图要一致性,以保证制作的顺利进行。二、原型制作是根据设计图纸和制作材料,可以是手绘也可以是3d软件创建。在此步骤中,要注意的问题是色彩和平面布局。三、动漫制作制作完成后,加工成型。完成不同的表现形式后,就要对设计稿进行加工处理,使加工的难易度降低,并得到一些基本准确的概念,以便于后续的大样、准确的尺寸制定。四、

  5. python ffmpeg 使用 pyav 转换 一组图像 到 视频 - 2

    2022/8/4更新支持加入水印水印必须包含透明图像,并且水印图像大小要等于原图像的大小pythonconvert_image_to_video.py-f30-mwatermark.pngim_dirout.mkv2022/6/21更新让命令行参数更加易用新的命令行使用方法pythonconvert_image_to_video.py-f30im_dirout.mkvFFMPEG命令行转换一组JPG图像到视频时,是将这组图像视为MJPG流。我需要转换一组PNG图像到视频,FFMPEG就不认了。pyav内置了ffmpeg库,不需要系统带有ffmpeg工具因此我使用ffmpeg的python包装p

  6. TimeSformer:抛弃CNN的Transformer视频理解框架 - 2

    Transformers开始在视频识别领域的“猪突猛进”,各种改进和魔改层出不穷。由此作者将开启VideoTransformer系列的讲解,本篇主要介绍了FBAI团队的TimeSformer,这也是第一篇使用纯Transformer结构在视频识别上的文章。如果觉得有用,就请点赞、收藏、关注!paper:https://arxiv.org/abs/2102.05095code(offical):https://github.com/facebookresearch/TimeSformeraccept:ICML2021author:FacebookAI一、前言Transformers(VIT)在图

  7. HBase Region 简介和建议数量&大小 - 2

    Region是HBase数据管理的基本单位,region有一点像关系型数据的分区。region中存储这用户的真实数据,而为了管理这些数据,HBase使用了RegionSever来管理region。Region的结构hbaseregion的大小设置默认情况下,每个Table起初只有一个Region,随着数据的不断写入,Region会自动进行拆分。刚拆分时,两个子Region都位于当前的RegionServer,但处于负载均衡的考虑,HMaster有可能会将某个Region转移给其他的RegionServer。RegionSplit时机:当1个region中的某个Store下所有StoreFile

  8. ruby-on-rails - Ruby 中意外的大小写行为 - 2

    我在一段非常简单的代码(如我所想)中得到了一个错误的值:org=4caseorgwhenorg=4val='H'endputsval=>nil请不要生气,我希望我错过了一些非常明显的东西,但我真的想不通。谢谢。 最佳答案 这是典型的Ruby错误。case有两种被调用的方法,一种是你传递一个东西作为分支的基础,另一种是你不传递的东西。如果您确实在case中指定了一个表达式语句然后评估所有其他条件并与===进行比较.在这种情况下org评估为false和org===false显然不是真的。所有其他情况也是如此,它们要么是真的,要么是假的。

  9. ruby - 确定 ruby​​ 脚本是否已经在运行 - 2

    有没有一种简单的方法可以判断ruby​​脚本是否已经在运行,然后适本地处理它?例如:我有一个名为really_long_script.rb的脚本。我让它每5分钟运行一次。当它运行时,我想看看之前运行的是否还在运行,然后停止第二个脚本的执行。有什么想法吗? 最佳答案 ps是一种非常糟糕的方法,并且可能会出现竞争条件。传统的Unix/Linux方法是将PID写入文件(通常在/var/run中)并在启动时检查该文件是否存在。例如pid文件位于/var/run/myscript.pid然后你会在运行程序之前检查它是否存在。有一些技巧可以避免

  10. ruby - 改变替换的大小写 - 2

    我有以下内容:text.gsub(/(lower)(upper)/,'\1\2')我可以将\2替换为大写吗?类似于:sed-e's/\(abc\)/\U\1/'这在Ruby中可行吗? 最佳答案 查看gsub文档:str.gsub(模式){|匹配|block}→new_str在block形式中,当前匹配字符串作为参数传入,$1、$2、$`、$&、$'等变量将被适当设置。block返回的值将替换为每次调用的匹配项。"alowerupperb".gsub(/(lower)(upper)/){|s|$1+""+$2.upcase}

随机推荐