Open ghost opened 6 years ago
this may or may not help.
public struct WWEVideo: Unboxable {
/*
"video_id": 1765,
"video_id_mlbam": 0,
"video_id_vms": 0,
"video_id_media_playback": 0,
"video_premium": false,
"video_show": {
"show_name": "Raw",
"show_color": "235,24,38,1",
"show_id": 1092
},
"video_season_id": 0,
"video_rating": "TV-PG",
"video_eventdate": "1/30/17",
"video_duration": 210,
"video_number_of_views": 319644991,
"video_type": "video",
"video_title": "Samoa Joe and Shinsuke Nakamura lay it all on the line for the NXT Championship in Osaka, Japan: WWE NXT Live Event, Dec. 3, 2016",
"video_description": "1000"
"video_thumbnail_image_name": "http://www.wwe.com/f/2016/12/007_007_nxt_12022016rf_3786_6c38bafebbd967e565f8eff0a9ee23f1--2c4adf3224d7a8423e831ba6dddabf4b.jpg",
"video_stream_url": "https://vod.wwe.com/vod/2016/,1080,720,540,432,360,288,/nxtosaka_joe_nakamura_matchclip.m3u8",
"video_stream_url_cc":"https:\/\/cdn1.wwe.com\/hd_video1\/wwe\/2017\/top30_sslam_moments_081217\/top30_sslam_moments_081217_cc_en.vtt",
"video_stream_url_mp4":"https:\/\/cdn1.wwe.com\/hd_video1\/wwe\/2017\/top30_sslam_moments_081217\/top30_sslam_moments_081217_640x360.mp4"
*/
var id: Int
var mID: String
var vms: Int
var mediaPlayback: Int
var premium: Bool // optional
var show: WWEShow? // optional
var seasonId: Int
var rating: String
var eventDate: String // WARNING - this is not return in associated content
var duration: Int
var viewCount: Int
var videoType: String
var title: String
var videoDescription: String
var thumbURL: String
var streamingURL: String
var streamingCC: String
var videoCount: Int
func url() -> URL {
//print("streamingURL = \(streamingURL)")
return URL(string: streamingURL)!
}
var playlistItems: [WWEVideo]?
init() {
id = 0
mID = ""
vms = 0
mediaPlayback = -1
premium = false
show = nil
seasonId = -1
videoCount = -1
rating = ""
eventDate = ""
duration = 100
viewCount = 0
videoType = ""
title = ""
videoDescription = ""
thumbURL = ""
streamingURL = ""
streamingCC = ""
playlistItems = []
}
public init(unboxer: Unboxer) throws {
do {
id = try unboxer.unbox(key: "video_id")
mID = try unboxer.unbox(key: "video_id_mlbam")
vms = try unboxer.unbox(key: "video_id_vms")
// optional
do {
mediaPlayback = try unboxer.unbox(key: "video_id_media_playback")
}catch{
mediaPlayback = -1
}
do {
premium = try unboxer.unbox(key: "video_premium")
}catch{
premium = false
}
if let _ = unboxer.dictionary["video_show"] {
show = try? unbox(dictionary: unboxer.dictionary, atKey: "video_show")
} else {
show = nil
}
do {
seasonId = try unboxer.unbox(key: "video_season_id")
} catch {
seasonId = -1 //to prevent quiting if this is null
}
do {
videoCount = try unboxer.unbox(key: "video_count")
} catch {
videoCount = -1 //to prevent quiting if this is null
}
do {
rating = try unboxer.unbox(key: "video_rating")
} catch {
rating = "" //to prevent quiting if this is null
}
do {
let strDate: String = try unboxer.unbox(key: "video_eventdate")
if let date: Date = DateFormatters.mdyFormatter.date(from: strDate) {
eventDate = DateFormatters.mdySpaceFormatter.string(from: date)
}else{
eventDate = ""
}
} catch {
eventDate = "" //to prevent quiting if this is null
}
duration = try unboxer.unbox(key: "video_duration")
viewCount = try unboxer.unbox(key: "video_number_of_views")
videoType = try unboxer.unbox(key: "video_type")
do {
title = try unboxer.unbox(key: "video_title")
} catch {
title = "" //to prevent quiting if this is null
}
do {
videoDescription = try unboxer.unbox(key: "video_description")
} catch {
videoDescription = "" //to prevent quiting if this is null
}
thumbURL = try unboxer.unbox(key: "video_thumbnail_image_name")
do {
streamingURL = try unboxer.unbox(key: "video_stream_url")
}catch{
streamingURL = ""
}
do {
streamingCC = try unboxer.unbox(key: "video_stream_url_cc")
}catch{
streamingCC = ""
}
if let _ = unboxer.dictionary["video_playlist_items"] {
playlistItems = try unbox(dictionary: unboxer.dictionary, atKey: "video_playlist_items")
} else {
playlistItems = []
}
}
}
func isPremium() -> Bool {
return premium
}
}
//
// ChromeCastPlayer.swift
// iOSChromecastSampleApp
//
import Foundation
import CoreMedia
import GoogleCast
import AVFoundation
import CocoaLumberjack
let kSubsIdentifier : Int = 99
class ChromeCastPlayer: NSObject {
var state: BasicPlayerState
var stateChange: Event<(old: BasicPlayerState, new: BasicPlayerState)>
var currentTime: CMTime
var currentTimeChange: Event<CMTime>
var duration: CMTime?
var curationChange: Event<CMTime?>
var currentBitrate: Double?
var currentBitrateChange: Event<Double?>
var maxBitrate: Double?
var maxResolution: CGSize?
let enableSDKLogging = true
override init() {
state = .null
stateChange = Event()
currentTime = CMTime.init()
currentTimeChange = Event()
curationChange = Event()
currentBitrateChange = Event()
GoogleCastLockControls.shared.setup()
super.init()
}
func getCastView( color:UIColor = .black) -> UIView {
let button = GCKUICastButton.init()
button.tintColor = color
return button
}
func openUrl( video: WWEVideo, contentType: String = "application/x-mpegurl", streamType: BasicPlayerStreamType = .vod, addToQueue:Bool = false,
callback:(Bool) -> Void
) {
if let session = GCKCastContext.sharedInstance().sessionManager.currentCastSession,
let remoteMediaClient = session.remoteMediaClient {
let metadata = GCKMediaMetadata(metadataType: .generic)
metadata.setString("Title", forKey: video.title)
metadata.setString("Subtitle", forKey: video.eventDate)
metadata.addImage(GCKImage(url: URL.init(string: video.thumbURL)! , width: 164, height: 82))
var duration : Double = Double(video.duration)
if (streamType == .live) { duration = TimeInterval.infinity }
var _streamType: GCKMediaStreamType = .buffered
if (streamType == .live) { _streamType = .live }
//Subtitle text style:
let textTrackStyle : GCKMediaTextTrackStyle = GCKMediaTextTrackStyle.createDefault()
textTrackStyle.backgroundColor = GCKColor(uiColor: .clear)
if let mediaInfo = video.mediaInfo(){
let requestOptions = GCKMediaLoadOptions()
if addToQueue{
requestOptions.autoplay = true
}
requestOptions.playPosition = 0
if video.hasSubTitles() && EZPlayerSettings.shared.closeCaptioning { //User's settings -> CC/subs enabled.
requestOptions.activeTrackIDs = [NSNumber(integerLiteral: kSubsIdentifier)]
}
let request = remoteMediaClient.loadMedia(mediaInfo, with: requestOptions)
request.delegate = ChromeCastManager.shared
remoteMediaClient.add(ChromeCastManager.shared)
GCKCastContext.sharedInstance().presentDefaultExpandedMediaControls()
}else{
DDLogError("🔥 FATAL: couldn't retrieve media info from video")
}
callback(true)
} else {
callback(false)
}
}
func play() {
if let session = GCKCastContext.sharedInstance().sessionManager.currentCastSession,
let remoteMediaClient = session.remoteMediaClient {
remoteMediaClient.play()
}
}
func pause() {
if let session = GCKCastContext.sharedInstance().sessionManager.currentCastSession,
let remoteMediaClient = session.remoteMediaClient {
remoteMediaClient.pause()
}
}
func seek(to: CMTime, callback: ((Bool) -> Void)?) {
if let session = GCKCastContext.sharedInstance().sessionManager.currentCastSession,
let remoteMediaClient = session.remoteMediaClient {
let seekOptions = GCKMediaSeekOptions()
seekOptions.interval = to.seconds
seekOptions.relative = false
seekOptions.resumeState = .play
remoteMediaClient.seek(with: seekOptions)
}
}
}
// MARK: - GCKLoggerDelegate
extension ChromeCastPlayer: GCKLoggerDelegate {
func logMessage(_ message: String, fromFunction function: String) {
if enableSDKLogging {
// Send SDK's log messages directly to the console.
print("\(function) \(message)")
}
}
}
// Chrome specific WWE video extension
extension WWEVideo{
func hasSubTitles()->Bool{
let videoHasSubs : Bool = !self.streamingCC.isEmpty && (self.streamingCC.lowercased().range(of: "http") != nil)
return videoHasSubs
}
func mediaInfo()-> GCKMediaInformation?{
let streamType:BasicPlayerStreamType = .vod;
let metadata = GCKMediaMetadata(metadataType: .generic)
metadata.setString("Title", forKey: self.title)
metadata.setString("Subtitle", forKey: self.eventDate)
metadata.addImage(GCKImage(url: URL.init(string: self.thumbURL)! , width: 164, height: 82))
var duration : Double = Double(self.duration)
if (streamType == .live) { duration = TimeInterval.infinity }
var _streamType: GCKMediaStreamType = .buffered
if (streamType == .live) { _streamType = .live }
func __getMediaTracks() -> [GCKMediaTrack]? {
//The media tracks represent the different audio streams and also the subtitles (unmutable)
//With the current sdk, filling the audio channels-tracks manually does not work (they appear, but don't load)
//After loadMedia, it will load the audio channells from m3u8 automatically, but leaving out possibility to start the video in the selected language
//Load subtitles
if self.hasSubTitles() {
var mediaTracks: [GCKMediaTrack] = [GCKMediaTrack]()
let mediaTrack = GCKMediaTrack(identifier: kSubsIdentifier,
contentIdentifier: self.streamingCC,
contentType: kKeySubtitle,
type: .text,
textSubtype: .subtitles,
name: "English CC",
languageCode: "en-us",
customData: nil)
mediaTracks.append(mediaTrack)
return mediaTracks
}
return nil
}
let textTrackStyle : GCKMediaTextTrackStyle = GCKMediaTextTrackStyle.createDefault()
textTrackStyle.backgroundColor = GCKColor(uiColor: .clear)
let info = GCKMediaInformation(
contentID: "\(self.id)",
streamType: .buffered,
contentType: "application/x-mpegurl",
metadata: metadata,
streamDuration: duration,
mediaTracks: __getMediaTracks(),
textTrackStyle: textTrackStyle,
customData: nil)
return info
}
}
@objc public enum BasicPlayerState: Int {
case null = 0
case paused = 1
case playing = 2
case failed = 3
func toString() -> String {
switch self {
case .null: return "null" // stopped
case .paused: return "paused"
case .playing: return "playing"
case .failed: return "failed"
}
}
}
enum BasicPlayerStreamType {
case live
case vod
}
public class Event<T> {
public typealias EventHandler = (T) -> ()
public var subscriptions = [Subscription<T>]()
@discardableResult func subscribe(_ target: AnyObject, _ handler: @escaping EventHandler) -> Subscription<T> {
let subscription = Subscription<T>(target: target, event: self, handler: handler)
subscriptions.append(subscription)
return subscription
}
func unsubscribe(_ target: AnyObject) {
subscriptions = subscriptions.filter { $0.target !== target }
}
@discardableResult func subscribe(_ handler: @escaping EventHandler) -> Subscription<T> {
let subscription = Subscription<T>(target: self, event: self, handler: handler)
subscriptions.append(subscription)
return subscription
}
func unsubscribe(_ subscription: Subscription<T>) {
subscriptions = subscriptions.filter { $0 !== subscription }
}
func trigger(_ value: T) {
subscriptions.forEach { (subscription) in
subscription.handler(value)
}
}
func dispose() {
subscriptions = []
}
}
public class Subscription<T> {
weak var target: AnyObject? = nil
let event: Event<T>
let handler: (T) -> ()
init(target: AnyObject, event: Event<T>, handler: @escaping (T) -> ()) {
self.target = target
self.event = event
self.handler = handler
}
func dispose() {
event.unsubscribe(self)
}
}
I have the vtt subtitles: http://dl.opensubtitles.org/en/download/subformat-vtt/filead/src-api/vrf-19e20c62/sid-3DjBbbDAOmE0miVvn9bn508EQRf/1954851996 But I can't cast to chromecast Please help me!