Code Monkey home page Code Monkey logo

mobileplayer-ios's Introduction

logo

MobilePlayer CocoaPods

codebeat badge CocoaPods Carthage compatible Dependencies StackOverflow Join the chat at https://gitter.im/mobileplayer/mobileplayer-ios

A powerful and completely customizable media player for iOS.

Table of Contents

  1. Features
  2. Installation
  3. Usage
  4. Customization
  1. Examples
  2. Documentation
  3. License

Features

  • Branding
    • Flexible skinning. Add a watermark, add/remove/move/resize interface elements, change their appearances and much more.
    • Easily set up A/B tests. You can manage multiple player skins and configurations. Player view controllers can load configuration data from a local JSON file or remote JSON data. You also have the option to initialize and pass configuration objects programmatically, which allows for greater flexibility.
  • Engagement
    • Comes with a built-in share button.
    • Standard sharing behavior can easily be modified.
    • Show any view controller as pre-roll or post-roll content.
    • Powerful overlay system. Add any view controller as an overlay to your video. Make them permanently visible, set them to appear in defined playback time intervals, or while playback is paused.
  • 100% documented.

Future plans

  • Well defined and extensive NSNotifications.
  • Volume button and volume slider elements.
  • Airplay support.
  • Plugin support.
  • Pre-bundled analytics plugins for various platforms.
  • VAST support.
  • Monetization.

Installation

Add the following line in your Podfile.

pod "MobilePlayer"

Add the following line to your Cartfile.

github "mobileplayer/mobileplayer-ios"

Usage

import MobilePlayer

let playerVC = MobilePlayerViewController(contentURL: videoURL)
playerVC.title = "Vanilla Player - \(videoTitle)"
playerVC.activityItems = [videoURL] // Check the documentation for more information.
presentMoviePlayerViewControllerAnimated(playerVC)

example-plain

Customization

Initialize using local configuration file

let bundle = NSBundle.mainBundle()
let config = MobilePlayerConfig(fileURL: bundle.URLForResource(
  "WatermarkedPlayer",
  withExtension: "json")!)
let playerVC = MobilePlayerViewController(
  contentURL: videoURL,
  config: config)
playerVC.title = "Watermarked Player - \(videoTitle)"
playerVC.activityItems = [videoURL]
present(playerVC, animated: true, completion: nil)

Initialize using remote configuration data

guard let configURL = NSURL(string: "https://goo.gl/c73ANK") else { return }
let playerVC = MobilePlayerViewController(
  contentURL: videoURL,
  config: MobilePlayerConfig(fileURL: configURL))
playerVC.title = "Watermarked Player - \(videoTitle)"
playerVC.activityItems = [videoURL]
present(playerVC, animated: true, completion: nil)

Configuration data

{
  "watermark": {
    "image": "MovielalaLogo"
  }
}

Without a configuration file URL

let playerVC = MobilePlayerViewController(
  contentURL: videoURL,
  config: MobilePlayerConfig(
    dictionary: ["watermark": ["image": "MovielalaLogo"]]))
playerVC.title = "Watermarked Player - \(videoTitle)"
playerVC.activityItems = [videoURL]
present(playerVC, animated: true, completion: nil)

Result example-customization

Skinning

{
  "watermark": {
    "image": "MovielalaLogo",
    "position": "topRight"
  },
  "topBar": {
    "backgroundColor": ["#a60500b0", "#a60500a0"],
    "elements": [
      {
        "type": "button",
        "identifier": "close"
      },
      {
        "type": "slider",
        "identifier": "playback",
        "trackHeight": 6,
        "trackCornerRadius": 3,
        "minimumTrackTintColor": "#eee",
        "availableTrackTintColor": "#9e9b9a",
        "maximumTrackTintColor": "#cccccc",
        "thumbTintColor": "#f9f9f9",
        "thumbBorderWidth": 1,
        "thumbBorderColor": "#fff",
        "marginRight": 4
      }
    ]
  },
  "bottomBar": {
    "backgroundColor": ["#a60500a0", "#a60500b0"],
    "elements": [
      {
        "type": "label",
        "text": "Now Watching",
        "font": "Baskerville",
        "size": 12,
        "marginLeft": 8,
        "marginRight": 8
      },
      {
        "type": "label",
        "identifier": "title",
        "size": 14
      },
      {
        "type": "button",
        "identifier": "action"
      },
      {
        "type": "toggleButton",
        "identifier": "play"
      }
    ]
  }
}

For all available identifiers, check the documentation or here. Same identifier value shouldn't be used more than once in a single configuration.

Result example-skinning

Example designs example-design-skinning

Showing overlays

let playerVC = MobilePlayerViewController(contentURL: videoURL)
playerVC.title = videoTitle
playerVC.activityItems = [videoURL]
present(playerVC, animated: true, completion: nil)
ProductStore.getProduct("1", success: { product in
  guard let product = product else { return }
  playerVC.showOverlayViewController(
    BuyOverlayViewController(product: product))
})

example-overlay

Showing timed overlays

let playerVC = MobilePlayerViewController(contentURL: videoURL)
playerVC.title = videoTitle
playerVC.activityItems = [videoURL]
present(playerVC, animated: true, completion: nil)
ProductStore.getProductPlacementsForVideo(
  videoID,
  success: { productPlacements in
    guard let productPlacements = productPlacements else { return }
    for placement in productPlacements {
      ProductStore.getProduct(placement.productID, success: { product in
        guard let product = product else { return }
        playerVC.showOverlayViewController(
          BuyOverlayViewController(product: product),
          startingAtTime: placement.startTime,
          forDuration: placement.duration)
      })
    }
})

example-timed-overlays

Pre-roll

let playerVC = MobilePlayerViewController(
  contentURL: videoURL,
  prerollViewController: PrerollOverlayViewController())
playerVC.title = videoTitle
playerVC.activityItems = [videoURL]
present(playerVC, animated: true, completion: nil)

example-preroll

Pause overlay

let playerVC = MobilePlayerViewController(
  contentURL: videoURL,
  pauseOverlayViewController: PauseOverlayViewController())
playerVC.title = videoTitle
playerVC.activityItems = [videoURL]
present(playerVC, animated: true, completion: nil)

Result example-pause-overlay

Example designs example-design-pause-overlay

Post-roll

let playerVC = MobilePlayerViewController(
  contentURL: videoURL,
  postrollViewController: PostrollOverlayViewController())
playerVC.title = videoTitle
playerVC.activityItems = [videoURL]
present(playerVC, animated: true, completion: nil)

Result example-postroll

Example designs example-design-postroll

Examples

After cloning the repo, run the MobilePlayerExamples target to see examples for many use cases. examples

Documentation

The entire documentation for the library can be found here.

License

The use of the MobilePlayer open source edition is governed by a Creative Commons license. You can use, modify, copy, and distribute this edition as long as it’s for non-commercial use, you provide attribution, and share under a similar license. http://mobileplayer.io/license/

mobileplayer-ios's People

Contributors

alejandroivan avatar andres-cianio avatar cemolcay avatar ebsaral avatar igorkulman avatar isair avatar jacks205 avatar lsolniczek avatar readmecritic avatar toygar avatar ty0x2333 avatar viniciussoares avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

mobileplayer-ios's Issues

Replaying video causes a crash

*** Terminating app due to uncaught exception 'CALayerInvalidGeometry', reason: 'CALayer position contains NaN: [nan 2]'
*** First throw call stack:
(
0 CoreFoundation 0x000000010eb27c65 exceptionPreprocess + 165
1 libobjc.A.dylib 0x000000011151dbb7 objc_exception_throw + 45
2 CoreFoundation 0x000000010eb27b9d +[NSException raise:format:] + 205
3 QuartzCore 0x00000001122ca336 _ZN2CA5Layer12set_positionERKNS_4Vec2IdEEb + 152
4 QuartzCore 0x00000001122ca4a8 -[CALayer setPosition:] + 43
5 QuartzCore 0x00000001122cab67 -[CALayer setFrame:] + 720
6 UIKit 0x000000010f433fdd -[UIView(Geometry) setFrame:] + 356
7 MobilePlayer 0x000000010e912a5b TFFC12MobilePlayer20CustomTimeSliderView14layoutSubviewsFS0_FT_T_U2_FT_T + 235
8 MobilePlayer 0x000000010e9124e7 _TTRXFo__dT__XFdCb__dT
+ 39
9 UIKit 0x000000010f43f422 +[UIView(UIViewAnimationWithBlocks) _setupAnimationWithDuration:delay:view:options:factory:animations:start:animationStateGenerator:completion:] + 473
10 UIKit 0x000000010f43f6fd +[UIView(UIViewAnimationWithBlocks) animateWithDuration:animations:] + 63
11 MobilePlayer 0x000000010e910d48 TFC12MobilePlayer20CustomTimeSliderView14layoutSubviewsfS0_FT_T + 2120
12 MobilePlayer 0x000000010e90fe47 TFC12MobilePlayer20CustomTimeSliderView25refreshBufferPercentRatiofS0_FT11bufferRatioV12CoreGraphics7CGFloat13totalDurationS2__T + 679
13 MobilePlayer 0x000000010e929ae3 TFC12MobilePlayer26MobilePlayerViewController21updateBufferInterfacefS0_FT_T + 755
14 MobilePlayer 0x000000010e92a152 TToFC12MobilePlayer26MobilePlayerViewController21updateBufferInterfacefS0_FT_T + 34
15 Foundation 0x000000010ef62744 NSFireTimer + 83
16 CoreFoundation 0x000000010ea8f174 __CFRUNLOOP_IS_CALLING_OUT_TO_A_TIMER_CALLBACK_FUNCTION
+ 20
17 CoreFoundation 0x000000010ea8ed35 __CFRunLoopDoTimer + 1045
18 CoreFoundation 0x000000010ea50d3d __CFRunLoopRun + 1901
19 CoreFoundation 0x000000010ea50366 CFRunLoopRunSpecific + 470
20 GraphicsServices 0x0000000111dfba3e GSEventRunModal + 161
21 UIKit 0x000000010f3c6900 UIApplicationMain + 1282
22 MobilePlayerExample 0x000000010e846d47 main + 135
23 libdyld.dylib 0x00000001111cd145 start + 1
24 ??? 0x0000000000000001 0x0 + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException

Pre-roll support

We currently have post-roll and pause-roll support, so there just needs to be a way to present a view controller before a video plays. Video should automatically start when the pre-roll view controller is dismissed.

Invalidate all timers on deinit

In viewDidLoad of MobilePlayerViewController we are creating three timers but none of them are being invalidated on deinit.

Use AVPlayerLayer

Migrate from subclassing MPMoviePlayerViewController to using an AVPlayerLayer as a sublayer.

Licensing

We need to pick a license or write one, and then add the license file to the repository.

Analytics plugin support

https://github.com/videojs/video.js/wiki/Plugins

Basic:
https://github.com/brightcove/videojs-overlay
https://github.com/brightcove/videojs-errors
https://github.com/mickey/videojs-ga


video-js-swf: Allows you to decode HLS videos with Flash within VideoJS.
videojs-youtube: Allows you to play YouTube videos within VideoJS.

Future:
videojs-vimeo: Allows you to play Vimeo videos within VideoJS.
videojs-dailymotion: Allows you to play Dailymotion videos within VideoJS.
videojs-soundcloud: Allows you to play soundcloud tracks within VideoJS.
videojs-wavesurfer: Adds a interactive waveform for audio and video files.
videojs-dashjs: Loads dash.js as a tech to support MPEG-DASH videos.
videojs-silverlight: Allows you to play WMV, WMA, MP4, MP3, WAV and FLAC medias through Silverlight within Video.js.
videojs-vlc: Allows you to play all media through VLC web plug-in within Video.js.
videojs-aurora: Allows you to play WAV, OGG, MP3, M4A, AAC and FLAC medias through Aurora.js within Video.js.
videojs-java: Allows you to play AIFF, AVI, GSM, MID, MPG, MP2, MOV, AU and WAV medias through Java within Video.js.

Play View

Top Dock Bar:

Title
Share ( Native Share)
More
Close

Test untested features

The following needs to be tested.

  • Skin file parsing.
  • Functionality of every property in config structures.
  • Video playback functionality.

Tests should be written using Quick.

Refactor project to increase code quality

  1. Refactor property and method names.
  2. Separate the main view controller into smaller view controllers (ControlbarViewController, TitlebarViewController, etc.)
  3. Refactor the logo mechanism to make it use showOverlayVC.
  4. Make sure the whole code is self documenting.

State property and state management

MobilePlayerViewController

public enum State {
  case Unknown, ...
}
public private(set) var state: State = .Unknown {
  didSet(oldValue) {
    previousState = oldValue
  }
}
public private(set) var previousState: State = .Unknown

StateHelper

private func stateForLoadState(loadState: MPMovieLoadState, andPlaybackState playbackState: MPMoviePlaybackState) -> MobilePlayerViewController.State {
  ...
}

Notes

  • MobilePlayerViewController uses StateHelper to determine which state to assign to itself when either its load state or playback state changes.
  • We don't need more than a single enum because MediaPlayer framework already defines enums for its states.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.