How do you play a video on watchOS with resizeAspectFill?

1.1k Views Asked by At

Play video in your watchOS app.

WKInterfaceMovie — An interface element that lets you play video and audio content in your watchOS app.


Works as expected. Video plays. What about scaling it to fill the screen?

  1. There’s a visual option in the storyboard. Selecting Resize Aspect Fill is ignored.

Screenshot of Xcode

  1. There’s a function for that: func setVideoGravity(_ videoGravity: WKVideoGravity)

The resizing option for the movie. For a list of possible values, see the WKVideoGravity type.


import WatchKit
import Foundation

class InterfaceController: WKInterfaceController {
    @IBOutlet weak var movieView: WKInterfaceMovie!

    override func awake(withContext context: Any?) {
        super.awake(withContext: context)

        setupVideoPlayer()
    }

    func setupVideoPlayer() {
        guard let videoURL = URL(string: "https://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4") else {
            return
    }

        movieView.setMovieURL(videoURL)
        movieView.setVideoGravity(.resizeAspectFill)
    }
}

Basic setup in Xcode. Video loads on tapping the play button. Plays after loading. Doesn’t fill screen.


WKVideoGravity

Constants indicating the appearance of video content.

case resizeAspectFill

Content is resized to fill the bounds rectangle completely while preserving the original aspect ratio of the content. This option results in cropping of the edges of the video in the axis it exceeds.

That’s perfect. Let’s try it.


It doesn’t work.

Regardless of videoGravity (in storyboard or code), the video plays resized to fit and only fills the screen if I double-tap.

What am I missing?


Additionally, if I explore the presentMediaPlayerController method with Media Player Options, there’s an odd behavior I've noticed:

WKMediaPlayerControllerOptionsAutoplayKey

WKMediaPlayerControllerOptionsStartTimeKey

WKMediaPlayerControllerOptionsVideoGravityKey (Fails and falls back to default behavior)

Overall, it appears to be broken. I’d love a workaround if anyone has ideas.

2

There are 2 best solutions below

0
Mosbah On

Apple APIs on the watch are buggy, this is clearly not working you can open a radar if you wish.

An alternative is to use a WKInterfaceInlineMovie ? you can format your video with desired aspect ratio (using ffmpeg or other tools), please see this code modified from Apple samples here .

class MovieDetailController: WKInterfaceController {
    @IBOutlet var inlineMovie :WKInterfaceInlineMovie!
    @IBOutlet var tapGestureRecognizer :WKTapGestureRecognizer!
    var playingInlineMovie :Bool = false

    override func awake(withContext context: Any?) {
        super.awake(withContext: context)

        // Setup the `inlineMovie` interface object with the URL to play.
        inlineMovie.setMovieURL(movieURL!)

        // Provide a poster image to be displayed in the inlineMovie interface object prior to playback.
        inlineMovie.setPosterImage(WKImage (imageName: "Ski1"))
        inlineMovie.setVideoGravity(.resize)

        // Movie playback starts
        playingInlineMovie = false
    }

    @IBAction func inlineMovieTapped(sender : AnyObject) {
        if playingInlineMovie == false {
            inlineMovie.play()
        } else {
            inlineMovie.pause()
        }

        playingInlineMovie = !playingInlineMovie
    }
}
2
Sagar koyani On

You should not set videogravity value programmatically. While they provide it in attribute inspector.

Set Video Gravity to Resize Aspect

Your attribute inspector should look like below snapshot.

enter image description here

And your code will be like below.

class InterfaceController: WKInterfaceController {
@IBOutlet weak var movieView: WKInterfaceMovie!

override func awake(withContext context: Any?) {
    super.awake(withContext: context)

    setupVideoPlayer()
}

func setupVideoPlayer() {
    guard let videoURL = URL(string: "https://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4") else {
        return
}
    movieView.setMovieURL(videoURL)
}}