Skip to content

Swift AVPlayer wrapper using the VIPER architecture. Currently a work in progress

License

Notifications You must be signed in to change notification settings

ustwo/videoplayback-ios

Repository files navigation

license pod pod

Summary

This framework is built using the VIPER (modified to VIPE) architecture. It started as an experiment with the architecture itself and is now a work in progress.

It is a swift wrapper around the AVFoundation framework. Use it to play remote, or local videos in a simple view or feed. Its purpose is to make playing progressive downloads and live streams simpler in your iOS applications

We also wrote a blog post on VIPER itself here: https://ustwo.com/blog/ins-and-outs-of-viper

Disclaimer:

This framework is a work in progress. Unit tests, VIPE refactoring, and bug fixes are pending.

Features

  • Scrub Video
  • Handle play or stop video in main thread
  • Play in UITableView
  • Autoplay video
  • HTTPS support
  • Written in Swift
  • Landscape support
  • Cocoapod support

Requirements

  • iOS 10.0 or later
  • Xcode 8.3 or later

Getting Started

  • Go to the "DemoVideoPlaybackKit" folder, run pod install. Open the workspace and build

About

The VIPER architecture has been talked about in the iOS community; however, it is uncommonly used. We wanted to gain an in depth understanding of this design pattern and see what the buzz was all about. As a result, we decided to test the following hypothesis:

As a developer I would like to use the VIPER design pattern to build reusable modules

We then decided to experiment with VIPER & playing video content. Playing video involves UI updates, data downloading & data syncrhonization. These complexities & interactions proved themselves to be worthwhile candidate for a VIPER structured module.

Communication

  • If you found a bug, open an issue.
  • If you have a feature request, open an issue.
  • If you want to contribute, submit a pull request.

Installation

  • pod install 'VideoPlaybackKit'

How To Use

import VideoPlaybackKit

Play a single video in a view - add a single view to your screen which contains video content

  1. Define the Video Type (local or remote). This is the ENTITY represented in the VIPER structure
let videoType = VPKVideoType.local(videoPathName: "Elon_Musk", fileType: "mp4", placeholderImageName: "elon_1")
  1. Build the video view
VPKVideoPlaybackBuilder.vpk_buildVideoView(for: videoType, shouldAutoplay: self.shouldAutoPlay, playbackBarTheme: self.toolBarTheme) { [weak self] (videoView) in

        self?.view.addSubview(videoView)
        videoView.snp.makeConstraints({ (make) in
        make.height.equalTo(self?.view.snp.height).dividedBy(2)
        make.top.equalTo(self?.view.snp.top).offset(10)
        make.left.right.equalTo(self?.view)
    })
}

Play a video in a feed

  1. Create a UITabieViewCell that conforms to VPKViewInCellProtocol
class VideoTableViewCell: UITableViewCell, VPKViewInCellProtocol {
    static let identifier = "VideoCell"
    var videoView: VPKVideoView? {
        didSet {
            self.setupVideoViewConstraints()
            layoutIfNeeded()
        }
    }
    
    override func prepareForReuse() {
        super.prepareForReuse()
        prepareForVideoReuse() //Extension default
    }
}
  1. Register cell in UIViewController, set up tableview. Add videoview to cell
    tableView.register(VideoTableViewCell.self, forCellReuseIdentifier: VideoTableViewCell.identifier)
    tableView.estimatedRowHeight = 400
    tableView.rowHeight = UITableViewAutomaticDimension

    datasource.asObservable().bind(to: tableView.rx.items(cellIdentifier: VideoTableViewCell.identifier)) { index, model, cell in
            
        guard let cell = cell as? VideoTableViewCell else { return }

        VPKVideoPlaybackBuilder.vpk_buildViewInCell(for: model, at: NSIndexPath(item: index, section: 0), completion: { [weak self] (videoView) in
                cell.videoView = videoView
                cell.layoutIfNeeded()
        })}.addDisposableTo(disposeBag)

        tableView.rx.setDelegate(self)
}

Autoplay Videos in a feed

  1. Conform to the VPKTableViewVideoPlaybackScrollable protocol

Implement the following:

extension FeedViewController: VPKTableViewVideoPlaybackScrollable {

    func scrollViewDidScroll(_ scrollView: UIScrollView) {
        handleAutoplayInTopVideoCell() // default implementation
        trackVideoViewCellScrolling() // default implementation
    }   

    func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
        if shouldAutoplayVideos {
            handleAutoplayInTopVideoCell()
        }
    }
}

Play video in feed, pre-fetch video asset data. *** Recommended especially for auto playing video in a feed ***

  1. Create a VPKTableViewPrefetchSynchronizer object
videoPrefetcher = VPKTableViewPrefetchSynchronizer(videoItems: datasource.value)
  1. Conform to the UITableViewDataSourcePrefetching tableview protocool
tableView.prefetchDataSource = self

extension FeedViewController: UITableViewDataSourcePrefetching {

    func tableView(_ tableView: UITableView, prefetchRowsAt indexPaths: [IndexPath]) {
        videoPrefetcher?.tableView(tableView, prefetchRowsAt: indexPaths)
    }

    func tableView(_ tableView: UITableView, cancelPrefetchingForRowsAt indexPaths: [IndexPath]) {
        videoPrefetcher?.tableView(tableView, cancelPrefetchingForRowsAt: indexPaths)
    }
}

Contact: