1

I am porting a showroom application from as3/starling to a native swift iPad app.

I have 2 questions:

  1. How can I fade a video over my spritekit content (from alpha 0 to 1).

  2. How to control the iPad volume with an individual UI element without showing the iOS onscreen-volume notification graphic.

Fluidity
  • 3,985
  • 1
  • 13
  • 34
bluelemonade
  • 1,115
  • 1
  • 14
  • 26
  • I'm working on a new answer for you that uses avPlayer and SKVideoNode, but allows you to adjust the volume and do seeking as well. – Fluidity Jul 08 '17 at 09:12

1 Answers1

1

My first answer answers your initial question, and this answer is tailored to the subsequent questions that were posted in the comments. I feel that both answers are useful to the community, instead of combining into just one which I think would be confusing.

Here I implement a volume slider and a scrubbing slider that controls the VideoNode's AVPlayer object.. you get the full power of the AVPlayer but with the convenience of the SKVideoNode. Also, the volume for playing video is controlled without having to adjust the system volume and subsequent gray sound box pop-up:

import SpriteKit
import MediaPlayer


class GameScene: SKScene {

  let seekSlider = UISlider(frame: CGRect(x: 0, y: 0, width: 200, height: 15))
  let volSlider  = UISlider(frame: CGRect(x: 0, y: 0, width: 200, height: 15))

  // Because it takes time for us to load the video, we don't know it's duration,
  // hence we don't know what the `.maximumValue` should be for the seekSlider
  let defaultMax = Float(0.123456789)

  var player: AVPlayer!
  var videoNode: SKVideoNode!

  func seekSliderChangedValue(sender: UISlider) {
    // Wait for file to finish loading so we can get accurate end duration:
      if sender.maximumValue == defaultMax {
      if CMTimeGetSeconds(player.currentItem!.duration).isNaN { return }
      else { sender.maximumValue = Float(CMTimeGetSeconds(player.currentItem!.duration)) }
    }

    let value = CMTimeMake(Int64(seekSlider.value), 1)
    player.seek(to: value)
    player.play()
  }

  func volSliderChangedValue(sender: UISlider) {
    player.volume = sender.value
  }

  override func didMove(to view: SKView) {
    removeAllChildren()  // Delete this in your actual project.

    // Add some labels:
    let seekLabel = SKLabelNode(text: "Seek")
    seekLabel.setScale(3)
    seekLabel.verticalAlignmentMode = .center
    seekLabel.position = CGPoint(x: frame.minX + seekLabel.frame.width/2,
                                 y: frame.maxY - seekLabel.frame.height)
    let volLabel  = SKLabelNode(text: "Volume")
    volLabel.setScale(3)
    volLabel.verticalAlignmentMode = .center
    volLabel.position = CGPoint(x: frame.minX + volLabel.frame.width/2,
                                y: frame.minY + volLabel.frame.height + volSlider.frame.height)

    // Make player and node:
    let url = Bundle.main.url(forResource: "sample", withExtension: "mp4")!
    player = AVPlayer(url: url)
    videoNode = SKVideoNode(avPlayer: player!)

    //Configure seek slider:
    seekSlider.addTarget(self, action: #selector(seekSliderChangedValue), for: UIControlEvents.valueChanged)
    seekSlider.maximumValue = defaultMax
    let seekOrigin = convertPoint(toView: CGPoint(x: seekLabel.frame.minX, y: seekLabel.frame.minY))
    seekSlider.frame = CGRect(origin: seekOrigin, size: CGSize(width: 200, height: 15))

    //Configure vol slider:
    volSlider.addTarget(self, action: #selector(volSliderChangedValue), for: UIControlEvents.valueChanged)
    volSlider.value = 1
    let volOrigin = convertPoint(toView: CGPoint(x: volLabel.frame.minX, y: volLabel.frame.minY))
    volSlider.frame = CGRect(origin: volOrigin, size: CGSize(width: 200, height: 15))

    //Scene stuff:
    view.addSubview(seekSlider)
    view.addSubview(volSlider)
    addChild(seekLabel)
    addChild(volLabel)
    addChild(videoNode)

    // Start video and animation:
    videoNode.alpha = 0
    videoNode.play()
    videoNode.run(.fadeIn(withDuration: 5))
  }
}
Fluidity
  • 3,985
  • 1
  • 13
  • 34
  • the video plays but no interface to seek the stream!?! – bluelemonade Jul 11 '17 at 08:01
  • hmm it shows up for me with seek and volume alider. i can take another look at it on a different device @bluelemonade – Fluidity Jul 11 '17 at 08:04
  • ok, I can see it both on simulator and device (ios 10) in portrait mode on iphone check out the updated github: https://github.com/fluidityt/BountyVideoFade – Fluidity Jul 11 '17 at 08:16
  • ok, on the iphone simulator I can see the UI, in landscape mode on an iPad there nothing. bytheway: when I am using a HD video, the image is cropped. – bluelemonade Jul 11 '17 at 08:43
  • @bluelemonade i cant write your whole app for you :) this is already the third answer ive given for one question. please accept it as answered and make a new question regarding landscape mode and cropping – Fluidity Jul 11 '17 at 08:46
  • @bluelemonade thanks for the bounty! Please don't forget to upvote and "accept answer" so others will benefit as well (knowing there is a good answer available) :) – Fluidity Jul 18 '17 at 23:53
  • @Fluidity, is it possible to play video from URL, i dont want to play it from main bundle. All example , resources uses local videos. I am not sure SKNODE supports player for streaming. Could you please check it ? – Jamshed Alam Aug 06 '19 at 04:48