Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(player): use new analytics endpoint #33

Merged
merged 3 commits into from
Jul 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ on: [push]

jobs:
test:
runs-on: macos-latest
runs-on: macos-13
steps:
- uses: actions/checkout@v3
- name: Set API key
Expand Down
2 changes: 1 addition & 1 deletion ApiVideoPlayer.podspec
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,5 @@ Pod::Spec.new do |s|
s.source_files = 'Sources/**/*.{swift, plist}'
s.resources = 'Sources/**/*.{storyboard,xib,xcassets,json,png}'

s.dependency "ApiVideoPlayerAnalytics", "1.1.1"
s.dependency "ApiVideoPlayerAnalytics", "2.0.0"
end
72 changes: 71 additions & 1 deletion ApiVideoPlayer.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,12 @@
21F14AE02C50E77A00B61588 /* ApiVideoPlayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 21F14ABD2C50E77A00B61588 /* ApiVideoPlayer.swift */; };
21F14AE12C50E77A00B61588 /* SwiftUIPlayerViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 21F14ABE2C50E77A00B61588 /* SwiftUIPlayerViewController.swift */; };
21F14AE42C50E7E500B61588 /* Media.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 21F14AE22C50E7E400B61588 /* Media.xcassets */; };
21F2E1042C52981000E833C2 /* ApiVideoPlayer.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 21BD67A82C51467B0039DEB6 /* ApiVideoPlayer.framework */; };
21F2E1052C52981000E833C2 /* ApiVideoPlayer.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 21BD67A82C51467B0039DEB6 /* ApiVideoPlayer.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
21F2E1082C52981800E833C2 /* ApiVideoPlayer.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 21BD67A82C51467B0039DEB6 /* ApiVideoPlayer.framework */; };
21F2E1092C52981800E833C2 /* ApiVideoPlayer.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 21BD67A82C51467B0039DEB6 /* ApiVideoPlayer.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
21F2E10C2C52A28000E833C2 /* ApiVideoPlayer.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 21BD67A82C51467B0039DEB6 /* ApiVideoPlayer.framework */; };
21F2E10D2C52A28000E833C2 /* ApiVideoPlayer.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 21BD67A82C51467B0039DEB6 /* ApiVideoPlayer.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
/* End PBXBuildFile section */

/* Begin PBXContainerItemProxy section */
Expand All @@ -89,6 +95,27 @@
remoteGlobalIDString = 21F149552C50DF0E00B61588;
remoteInfo = ApiVidePlayer;
};
21F2E1062C52981000E833C2 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 21F1494D2C50DF0E00B61588 /* Project object */;
proxyType = 1;
remoteGlobalIDString = 21F149552C50DF0E00B61588;
remoteInfo = ApiVideoPlayer;
};
21F2E10A2C52981800E833C2 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 21F1494D2C50DF0E00B61588 /* Project object */;
proxyType = 1;
remoteGlobalIDString = 21F149552C50DF0E00B61588;
remoteInfo = ApiVideoPlayer;
};
21F2E10E2C52A28000E833C2 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 21F1494D2C50DF0E00B61588 /* Project object */;
proxyType = 1;
remoteGlobalIDString = 21F149552C50DF0E00B61588;
remoteInfo = ApiVideoPlayer;
};
/* End PBXContainerItemProxy section */

/* Begin PBXCopyFilesBuildPhase section */
Expand All @@ -98,6 +125,7 @@
dstPath = "";
dstSubfolderSpec = 10;
files = (
21F2E1052C52981000E833C2 /* ApiVideoPlayer.framework in Embed Frameworks */,
);
name = "Embed Frameworks";
runOnlyForDeploymentPostprocessing = 0;
Expand All @@ -108,6 +136,18 @@
dstPath = "";
dstSubfolderSpec = 10;
files = (
21F2E1092C52981800E833C2 /* ApiVideoPlayer.framework in Embed Frameworks */,
);
name = "Embed Frameworks";
runOnlyForDeploymentPostprocessing = 0;
};
21F2E1102C52A28000E833C2 /* Embed Frameworks */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = "";
dstSubfolderSpec = 10;
files = (
21F2E10D2C52A28000E833C2 /* ApiVideoPlayer.framework in Embed Frameworks */,
);
name = "Embed Frameworks";
runOnlyForDeploymentPostprocessing = 0;
Expand Down Expand Up @@ -209,6 +249,7 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
21F2E10C2C52A28000E833C2 /* ApiVideoPlayer.framework in Frameworks */,
21B395962C51340900451CF1 /* ApiVideoClient in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
Expand All @@ -217,13 +258,15 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
21F2E1042C52981000E833C2 /* ApiVideoPlayer.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
21F14A712C50E22200B61588 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
21F2E1082C52981800E833C2 /* ApiVideoPlayer.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down Expand Up @@ -285,6 +328,7 @@
21BD67A82C51467B0039DEB6 /* ApiVideoPlayer.framework */,
21BD67A92C51467B0039DEB6 /* Example iOS.app */,
21BD67AA2C51467B0039DEB6 /* Example iOSSwiftUI.app */,
21F2E1032C52981000E833C2 /* Frameworks */,
);
sourceTree = "<group>";
};
Expand Down Expand Up @@ -499,6 +543,13 @@
path = Resources;
sourceTree = "<group>";
};
21F2E1032C52981000E833C2 /* Frameworks */ = {
isa = PBXGroup;
children = (
);
name = Frameworks;
sourceTree = "<group>";
};
/* End PBXGroup section */

/* Begin PBXHeadersBuildPhase section */
Expand Down Expand Up @@ -540,11 +591,13 @@
21F1495C2C50DF0F00B61588 /* Sources */,
21F1495D2C50DF0F00B61588 /* Frameworks */,
21F1495E2C50DF0F00B61588 /* Resources */,
21F2E1102C52A28000E833C2 /* Embed Frameworks */,
);
buildRules = (
);
dependencies = (
21F149632C50DF0F00B61588 /* PBXTargetDependency */,
21F2E10F2C52A28000E833C2 /* PBXTargetDependency */,
);
name = ApiVideoPlayerTests;
packageProductDependencies = (
Expand All @@ -567,6 +620,7 @@
);
dependencies = (
21B395602C50EE0300451CF1 /* PBXTargetDependency */,
21F2E1072C52981000E833C2 /* PBXTargetDependency */,
);
name = "Example iOS";
productName = iOSExampleUIKit;
Expand All @@ -586,6 +640,7 @@
);
dependencies = (
21B395652C50FA7B00451CF1 /* PBXTargetDependency */,
21F2E10B2C52981800E833C2 /* PBXTargetDependency */,
);
name = "Example iOSSwiftUI";
productName = iOSExampleSwiftUI;
Expand Down Expand Up @@ -776,6 +831,21 @@
target = 21F149552C50DF0E00B61588 /* ApiVideoPlayer */;
targetProxy = 21F149622C50DF0F00B61588 /* PBXContainerItemProxy */;
};
21F2E1072C52981000E833C2 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 21F149552C50DF0E00B61588 /* ApiVideoPlayer */;
targetProxy = 21F2E1062C52981000E833C2 /* PBXContainerItemProxy */;
};
21F2E10B2C52981800E833C2 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 21F149552C50DF0E00B61588 /* ApiVideoPlayer */;
targetProxy = 21F2E10A2C52981800E833C2 /* PBXContainerItemProxy */;
};
21F2E10F2C52A28000E833C2 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 21F149552C50DF0E00B61588 /* ApiVideoPlayer */;
targetProxy = 21F2E10E2C52A28000E833C2 /* PBXContainerItemProxy */;
};
/* End PBXTargetDependency section */

/* Begin PBXVariantGroup section */
Expand Down Expand Up @@ -1237,7 +1307,7 @@
repositoryURL = "https://github.com/apivideo/api.video-swift-player-analytics";
requirement = {
kind = exactVersion;
version = 1.1.1;
version = 2.0.0;
};
};
/* End XCRemoteSwiftPackageReference section */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,13 @@
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<EnvironmentVariables>
<EnvironmentVariable
key = "IDEPreferLogStreaming"
value = "YES"
isEnabled = "YES">
</EnvironmentVariable>
</EnvironmentVariables>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
Expand Down
4 changes: 2 additions & 2 deletions Package.resolved
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/apivideo/api.video-swift-player-analytics",
"state" : {
"revision" : "a9811da994c2dedbd387888c92e292abfd738948",
"version" : "1.1.1"
"revision" : "fe35c711a9667a010d921c39364c30ffe8b02e32",
"version" : "2.0.0"
}
}
],
Expand Down
2 changes: 1 addition & 1 deletion Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ let package = Package(
dependencies: [
// Dependencies declare other packages that this package depends on.
// .package(url: /* package url */, from: "1.0.0"),
.package(url: "https://github.com/apivideo/api.video-swift-player-analytics", exact: "1.1.1"),
.package(url: "https://github.com/apivideo/api.video-swift-player-analytics", exact: "2.0.0"),
.package(url: "https://github.com/apivideo/api.video-swift-client", exact: "1.2.1")
],
targets: [
Expand Down
57 changes: 2 additions & 55 deletions Sources/ApiVideoPlayer/Player/ApiVideoPlayerController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,7 @@ import MediaPlayer
/// It is used internally of the ``ApiVideoPlayerView``.
/// It could be used directly if you want to use the player with a fully custom UI.
public class ApiVideoPlayerController: NSObject {
internal let player = AVPlayer(playerItem: nil)
private var analytics: PlayerAnalytics?
internal let player = ApiVideoAnalyticsAVPlayer(playerItem: nil)
private var timeObserver: Any?
private var isFirstPlay = true
private var isSeeking = false
Expand Down Expand Up @@ -163,9 +162,7 @@ public class ApiVideoPlayerController: NSObject {
name: .AVPlayerItemDidPlayToEndTime,
object: playerItem
)
if let urlAsset = playerItem.asset as? AVURLAsset {
self.setUpAnalytics(url: urlAsset.url.absoluteString)
}

}

private func notifyError(error: Error) {
Expand Down Expand Up @@ -209,15 +206,6 @@ public class ApiVideoPlayerController: NSObject {
player.removeTimeObserver(observer)
}

private func setUpAnalytics(url: String) {
do {
let option = try Options(mediaUrl: url)
self.analytics = PlayerAnalytics(options: option)
} catch {
print("Failed to initiate analytics for \(url)")
}
}

/// Get if the player is playing a live stream.
/// - Returns: True if the player is playing a live stream
public var isLive: Bool {
Expand Down Expand Up @@ -251,18 +239,7 @@ public class ApiVideoPlayerController: NSObject {
}

private func seekImpl(to time: CMTime, completion: @escaping (Bool) -> Void) {
let from = self.currentTime
self.player.seek(to: time, toleranceBefore: .zero, toleranceAfter: .zero) { completed in
self.analytics?
.seek(
from: Float(max(0, from.seconds)),
to: Float(max(0, time.seconds))
) { result in
switch result {
case .success: break
case let .failure(error): print("Failed to send seek event to analytics: \(error)")
}
}
self.infoNowPlaying.updateCurrentTime(currentTime: time)
completion(completed)
}
Expand Down Expand Up @@ -514,12 +491,6 @@ public class ApiVideoPlayerController: NSObject {
self.replay()
self.multicastDelegate.didLoop()
}
self.analytics?.end { result in
switch result {
case .success: break
case let .failure(error): print("Failed to send end event to analytics: \(error)")
}
}
self.multicastDelegate.didEnd()
}

Expand Down Expand Up @@ -578,12 +549,6 @@ public class ApiVideoPlayerController: NSObject {
if self.autoplay {
self.play()
}
self.analytics?.ready { result in
switch result {
case .success: break
case let .failure(error): print("Failed to send ready event to analytics: \(error)")
}
}
}
}

Expand All @@ -596,12 +561,6 @@ public class ApiVideoPlayerController: NSObject {
return
}

self.analytics?.pause { result in
switch result {
case .success: break
case let .failure(error): print("Failed to send pause event to analytics: \(error)")
}
}
self.infoNowPlaying.pause(currentTime: self.currentTime)
self.multicastDelegate.didPause()
}
Expand All @@ -623,19 +582,7 @@ public class ApiVideoPlayerController: NSObject {
)

#endif
self.analytics?.play { result in
switch result {
case .success: break
case let .failure(error): print("Failed to send play event to analytics: \(error)")
}
}
} else {
self.analytics?.resume { result in
switch result {
case .success: break
case let .failure(error): print("Failed to send resume event to analytics: \(error)")
}
}
self.infoNowPlaying.play(currentTime: self.currentTime)
}
#if !os(macOS)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,25 +10,27 @@ final class AVPlayerExtensions: XCTestCase {
_ = observer.readyExpectation

let avPlayer = AVPlayer(playerItem: nil)
avPlayer.addObserver(observer, forKeyPath: "status", options: .new, context: nil)
avPlayer.replaceCurrentItem(withHls: VideoOptions(videoId: VideoId.validVideoId, videoType: .vod))
avPlayer.currentItem?.addObserver(observer, forKeyPath: "status", options: .new, context: nil)

avPlayer.play()

waitForExpectations(timeout: 10, handler: nil)
avPlayer.currentItem?.removeObserver(observer, forKeyPath: "status")
avPlayer.removeObserver(observer, forKeyPath: "status")
}

func testValidMP4VideoIdPlay() throws {
let observer = AVPlayerReadyObserverImpl(testCase: self)
_ = observer.readyExpectation

let avPlayer = AVPlayer(playerItem: nil)
avPlayer.addObserver(observer, forKeyPath: "status", options: .new, context: nil)
avPlayer.replaceCurrentItem(withMp4: VideoOptions(videoId: VideoId.validVideoId, videoType: .vod))
avPlayer.currentItem?.addObserver(observer, forKeyPath: "status", options: .new, context: nil)

avPlayer.play()

waitForExpectations(timeout: 10, handler: nil)
avPlayer.currentItem?.removeObserver(observer, forKeyPath: "status")
avPlayer.removeObserver(observer, forKeyPath: "status")
}
}

Expand Down
Loading