Giter Site home page Giter Site logo

wxxsw / gsplayer Goto Github PK

View Code? Open in Web Editor NEW
382.0 10.0 92.0 184 KB

⏯ Video player, support for caching, preload, fullscreen transition and custom control view. 视频播放器,支持边下边播、预加载、全屏转场和自定义控制层

License: MIT License

Swift 98.65% Ruby 1.35%
player swift video videocache

gsplayer's Introduction

GSPlayer

Features

  • Fully customizable UI.
  • Easy to use API and callbacks.
  • Built-in caching mechanism to support playback while downloading (mp4).
  • Can preload multiple videos at any time.
  • Can be embedded into UITableView and UICollectionView.
  • Provide full screen transition.
  • Complete Demo.

Quick Start

  1. Add VideoPlayerView to the interface.
let playerView = VideoPlayerView()
view.addSubview(playerView)

// Or in IB, specify the type of custom View as VideoPlayerView.
  1. Play Video.
playerView.play(for: someURL)
  1. Pause/Resume Video.
if playerView.state == .playing {
    playerView.pause(reason: .userInteraction)
} else {
    playerView.resume()
}
  1. Update control UI based on playback status.
playerView.stateDidChanged = { state in
    switch state {
    case .none:
        print("none")
    case .error(let error):
        print("error - \(error.localizedDescription)")
    case .loading:
        print("loading")
    case .paused(let playing, let buffering):
        print("paused - progress \(Int(playing * 100))% buffering \(Int(buffering * 100))%")
    case .playing:
        print("playing")
    }
}

Documents

Cache

Get the total size of the video cache.

VideoCacheManager.calculateCachedSize()

Clean up all caches.

VideoCacheManager.cleanAllCache()

Preload

Set the video URL to be preloaded. Preloading will automatically cache a short segment of the beginning of the video and decide whether to start or pause the preload based on the buffering of the currently playing video.

VideoPreloadManager.shared.set(waiting: [URL])

Set the preload size, the default value is 1024 * 1024, unit is byte.

VideoPlayer.preloadByteCount = 1024 * 1024 // = 1M

Fullscreen

See demo.

PlayerView

Property

An object that manages a player's visual output.

public let playerLayer: AVPlayerLayer { get }

Get current video status.

public enum State {

    /// None
    case none

    /// From the first load to get the first frame of the video
    case loading

    /// Playing now
    case playing

    /// Pause, will be called repeatedly when the buffer progress changes
    case paused(playing: Double, buffering: Double)

    /// An error occurred and cannot continue playing
    case error(NSError)
}

public var state: State { get }

The reason the video was paused.

public enum PausedReason {

    /// Pause because the player is not visible, stateDidChanged is not called when the buffer progress changes
    case hidden

    /// Pause triggered by user interaction, default behavior
    case userInteraction

    /// Waiting for resource completion buffering
    case waitingKeepUp
}

public var pausedReason: PausedReason { get }

Number of replays.

public var replayCount: Int { get }

Played progress, value range 0-1.

public var playing: Double { get }

Played length in seconds.

public var currentDuration: Double { get }

Buffered progress, value range 0-1.

public var buffering: Double { get }

Buffered length in seconds.

public var currentBufferDuration: Double { get }

Total video duration in seconds.

public var totalDuration: Double { get }

The total watch time of this video, in seconds.

public var watchDuration: Double { get }

Whether the video is muted, only for this instance.

public var isMuted: Bool { get set }

Video volume, only for this instance.

public var volume: Double { get set }

Callback

Playback status changes, such as from play to pause.

public var stateDidChanged: ((State) -> Void)?

Replay after playing to the end.

public var replay: (() -> Void)?

Method

Play a video of the specified url.

func play(for url: URL)

Pause video.

func pause(reason: PausedReason)

Continue playing video.

func resume()

Installation

GSPlayer is available through CocoaPods. To install it, simply add the following line to your Podfile:

pod 'GSPlayer'

Contribution

Issue

If you find a bug or need a help, you can create a issue

Pull Request

We are happy to accept pull requests :D. But please make sure it's needed by most developers and make it simple to use. If you are not sure, create an issue and we can discuss it before you get to coding.

License

The MIT License (MIT)

gsplayer's People

Contributors

gbuela avatar huizhenhe-dev avatar kkaliher avatar phongngo511 avatar umairalitail avatar v57 avatar wxxsw avatar yspreen 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

gsplayer's Issues

Video stuck when the internet speeds slow At that time I need to display buffer loader so please help me how to set loader when the video goes to buffer.

@barotbhavesh

playerView.stateDidChanged = { [weak self] state in
    guard let self = self else { return }
    
    if case .paused = state, self.playerView.pausedReason == .waitingKeepUp {
        // buffering
    }
}

Originally posted by @wxxsw in #13 (comment)

I am trying the given solution but when the video goes to buffer at that time "state" I am getting ".playing" and I am adding the condition on

case .playing:
if case .paused = state, self.playerView?.pausedReason == .waitingKeepUp {
self.activityIndicator.startAnimating()
} else if case .playing = state, self.playerView?.pausedReason == .waitingKeepUp {
self.activityIndicator.startAnimating()
} else {
self.activityIndicator.stopAnimating()
}

and one more thing I am also getting "self.playerView?.pausedReason == .waitingKeepUp" when video playing

[Request] Video Controls

Hello, Thank you for this awesome code, it would be nice if you can add basic controls over the layout which can be disabled and enabled.

Best regards.

Low bandwidth videos stop.

720p and 360p video urls are coming from the service. Let the user watch the 720p video at first. If the bandwidth is low, the video will continue from where it left off in 360p.

How can I achieve this scenario?

Previous Video Not Stop/Pause

Getting one issue in example when moving from one video to another . Previous Video does not pause or stop due to this current video sound mix with previous video. Like first row video played and then we move to next row video ideally previous video should stop or pause.

Preload - Buffer a specific time

Hello,

is there any way to do that? For example I have 5 urls and I want buffering all of urls with start a specific timestamp like start buffering at 3 mins and continue buffering with specified byte

thank you

m3u8 Cache

Pls Add m3u8 support for Cache and Preloading like TIKTOK

Playback continous stalling

Trying to load a video with high bitrate (more than 2MB/s), playback keeps getting stalled.

{
"transportType" : "HTTP Progressive Download",
"mediaType" : "HTTP Progressive Download",
"BundleID" : "GSPlayer_Example",
"name" : "MEDIA_PLAYBACK_STALL",
"interfaceType" : "Other"
}

Any assistance would be much appreciated.

SPM minimum iOS Version

Hello, I am using xcode 13.1 and my project deployment target is iOS 11.0, but I'm getting this error on build:
Compiling for iOS 11.0, but module 'GSPlayer' has a minimum deployment target of iOS 13.0: /GSPlayer.swiftmodule/x86_64-apple-ios-simulator.swiftmodule

Is it possible to add http request header?

Is it possible to add http request header? E.g. adding a header for "Referer".
Sometimes we need to check the referer to limit hot links.

This feature is quite commonly seen in other library like Alamofire.

Thanks

Audio keeps playing after closing controller

I have a controller with collectionCell. Everything works fine but when I pop the controller when the video is playing the audio doesn't stop.
Is there any global setting which I can set that will make my AVPlayer stop playing the audio?

error - Cannot Decode

The player issue can't decode the URL but before sometime working fine on the same URL.

next and previous button

hello.

I added Next and Previous buttons for playing multiple videos but there is a problem with changing video

 @IBAction func nextAction(_ sender: Any) {

        playerView.play(for: URL(string: "http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/ElephantsDream.mp4")!) // next video's url
    }

this is the way I'm changing the videos //

crash on removing time observer when videoView is in tableView

i get this crash a lot whenever i try remove timeObserver

An instance of AVPlayer cannot remove a time observer that was added by a different instance of AVPlayer.

my code:

private func removeObserver() {
        
        if let token = timeObserverToken {
            videoView.removeTimeObserver(token)
            timeObserverToken = nil
        }
        
    }

MacOS

  1. I use this code on MacOS, and find the following code will always cancel request.

func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive response: URLResponse, completionHandler: @escaping (URLSession.ResponseDisposition) -> Void) {
guard
let mimeType = response.mimeType,
mimeType.hasPrefix("video/")
else { completionHandler(.cancel); return }

  1. I also change some codes for supporting MacOS, can I commit?

example using UICollectionViewDataSourcePrefetching

    collectionView.isPrefetchingEnabled = true
      collectionView.prefetchDataSource = self

extension VideoVC: UICollectionViewDataSourcePrefetching {

    func collectionView(_ collectionView: UICollectionView, prefetchItemsAt indexPaths: [IndexPath]) {

        for indexPath in indexPaths {

            // PREFETCH THE VIDEO

        }
    }
    func collectionView(_ collectionView: UICollectionView, cancelPrefetchingForItemsAt indexPaths: [IndexPath]) {
        // Cancel any requests for data for the specified index paths.
        for indexPath in indexPaths {
            if let video = self.theatreDataSource?.itemIdentifier(for: indexPath) {
                print("cancel downloading video:", video)
            }
        }
    }
}

should I be using
VideoPreloadManager or VideoDownloader to kick off the eager download?

Can not play video from googlevideo.com

Cache

Good morning, I would like to set a limit on the size of the caches. Therefore I wrote a function that is called on the launch of the app if the size of the caches exceeds my limit. The function iterates through the cache folder and deletes files until the cache size is in the limit. Do you think this function could interfere with the normal behavior of the library? Thanks in advance

   func cleanGSPlayerCache(){
        DispatchQueue.global(qos: .background).async {
            do{
                var size = VideoCacheManager.calculateCachedSize()
                let directory = NSTemporaryDirectory().appending("GSPlayer")
                let fileManager = FileManager.default
                let resourceKeys: Set<URLResourceKey> = [.totalFileAllocatedSizeKey]
                let fileContents = try fileManager.contentsOfDirectory(at: URL(fileURLWithPath: directory), includingPropertiesForKeys: Array(resourceKeys))
                
                for fileContent in fileContents{
                    guard let resourceValues = try? fileContent.resourceValues(forKeys: resourceKeys), let fileSize = resourceValues.totalFileAllocatedSize else {continue}
                    
                    if (try? fileManager.removeItem(atPath: fileContent.path)) != nil{
                        size -= UInt(fileSize)
                        if size <= self.maxVideoDiskCacheSize{
                            break
                        }
                    }
                }
            }catch{
                print("Could not clean GSPlayer cache")
            }
        }
    }

In the AppDelegate:

        if VideoCacheManager.calculateCachedSize() > self.maxVideoDiskCacheSize {
            self.cleanGSPlayerCache()
        }

Random crash while streaming video

I've been getting this exc_bad_access crash repeatedly now both while my video is playing and while the video is seeking.

Screen Shot 2021-01-30 at 3 36 24 AM

If it helps, these are relatively large mp4 files (500MB+) that I'm streaming. Let me know if there's any more info I can get you.

preload for m3u8 video file.

@wxxsw Could you please suggest how to preload m3u8 files too like mp4. I need to implement preload and prefetch functionality for m3u8 files like Instagram does in the reels section. Any idea how we can play videos in the next cell scroll without showing buffer loader.
Like Instagram, We want to prefetch some % of all videos and remaining at the time of video playing

Video buffer playing issue

Is any way to play buffer video just an Example
My video goes to buffer at that time video stuck and buffer time is increase 55% ..56%..60%...and 100%. After 100% video play with start.
I need to when the video goes to buffer like 55% and then buffer time going to 75% in between 55% to 75% VIDEO WANTS TO PLAY BUT IN current scenario video not play.

can you please help me with how to handle this issue?

Video play problem

when play video, it prompt the following error:
2021-03-14 07:45:16.571105+0800 Weishi[87431:1440614] NSURLConnection finished with error - code -1002
2021-03-14 07:45:16.572115+0800 Weishi[87431:1440514] NSURLConnection finished with error - code -1002
2021-03-14 07:45:16.573121+0800 Weishi[87431:1440616] NSURLConnection finished with error - code -1002
2021-03-14 07:45:16.574477+0800 Weishi[87431:1440616] NSURLConnection finished with error - code -1002
2021-03-14 07:45:16.575507+0800 Weishi[87431:1440514] NSURLConnection finished with error - code -1002
2021-03-14 07:45:16.577831+0800 Weishi[87431:1440616] NSURLConnection finished with error - code -1002
2021-03-14 07:45:16.578846+0800 Weishi[87431:1440514] NSURLConnection finished with error - code -1002
2021-03-14 07:45:16.579975+0800 Weishi[87431:1440618] NSURLConnection finished with error - code -1002
2021-03-14 07:45:16.588161+0800 Weishi[87431:1440690] [Symptoms] {
"transportType" : "HTTP Progressive Download",
"mediaType" : "HTTP Progressive Download",
"BundleID" : "Weishi",
"name" : "MEDIA_PLAYBACK_STALL",
"interfaceType" : "Other"
}

  • Send failure: Broken pipe

Duration confusion

The API gives a few different confusing durations:

  • currentBufferDuration
  • watchDuration
  • currentDuration
  • totalDuration

What do they mean?

I would like to find:

  1. The current time the video is at.
  2. The total duration of the video.

Video Stretching on full screen

When we play video in full screen on UIView video will stretched
I have tried to set content mode as aspect fill or aspect fit but not fixed

Video not playing properly, Something break the voice between playing in release 0.2.18

Kindly check this video https://www.dropbox.com/s/pc4hgxhrylejwj4/rpreplay_final1605605155.mp4?dl=0

Not an internet connection issue and tested speeds.
I have tried to figure out the issue and found continuous call paused state did change. Buffer progress goes 0.9 and after the start with again buffer Progress 0.

If kill the app and open the same video then that video, not an issue. This issue occurs randomly.

case .paused(let playProgress, let bufferProgress):

PlayerView pausedReason waitingKeepUp playProgress: 0.33890865789099006 bufferProgress:0.22409982008568582
PlayerView pausedReason waitingKeepUp playProgress: 0.3794132463531757 bufferProgress:0.22409982008568582
PlayerView pausedReason waitingKeepUp playProgress: 0.4181798884272383 bufferProgress:0.22409982008568582
PlayerView pausedReason waitingKeepUp playProgress: 0.45868613365433153 bufferProgress:0.22409982008568582
PlayerView pausedReason waitingKeepUp playProgress: 0.4979489768182348 bufferProgress:0.22409982008568582
PlayerView pausedReason waitingKeepUp playProgress: 0.5367147905098435 bufferProgress:0.22409982008568582
PlayerView pausedReason waitingKeepUp playProgress: 0.5767231778821885 bufferProgress:0.22409982008568582
PlayerView pausedReason waitingKeepUp playProgress: 0.5918817484047166 bufferProgress:0.5966052498738011
PlayerView pausedReason waitingKeepUp playProgress: 0.6318917925419693 bufferProgress:0.6368626956082787
PlayerView pausedReason waitingKeepUp playProgress: 0.6718993515318604 bufferProgress:0.6718993515318604
PlayerView pausedReason waitingKeepUp playProgress: 0.7106651652234691 bufferProgress:0.6718993515318604
PlayerView pausedReason waitingKeepUp playProgress: 0.7499288367698262 bufferProgress:0.6718993515318604
PlayerView pausedReason waitingKeepUp playProgress: 0.7904350819969195 bufferProgress:0.6718993515318604
PlayerView pausedReason waitingKeepUp playProgress: 0.829696268395915 bufferProgress:0.7904370364617715
PlayerView pausedReason waitingKeepUp playProgress: 0.8689607683247259 bufferProgress:0.7904370364617715
PlayerView pausedReason waitingKeepUp playProgress: 0.9082227831061753 bufferProgress:0.8689618685201724
PlayerView pausedReason waitingKeepUp playProgress: 0.9474864546525325 bufferProgress:0.9082242845493729
PlayerView pausedReason waitingKeepUp playProgress: 0.9879935282620796 bufferProgress:0.9474867005785734
PlayerView pausedReason waitingKeepUp playProgress: 0.18453296056122914 bufferProgress:0.1888711994719062
PlayerView pausedReason waitingKeepUp playProgress: 0.22379580372513236 bufferProgress:0.18950219391915507
PlayerView pausedReason waitingKeepUp playProgress: 0.26305947527148943 bufferProgress:0.18950219391915507
PlayerView pausedReason waitingKeepUp playProgress: 0.301826117345552 bufferProgress:0.18950219391915507
PlayerView pausedReason waitingKeepUp playProgress: 0.34233070580773767 bufferProgress:0.18950219391915507
PlayerView pausedReason waitingKeepUp playProgress: 0.3815943773540947 bufferProgress:0.18950219391915507
PlayerView pausedReason waitingKeepUp playProgress: 0.42085722051799795 bufferProgress:0.38159631887547085
PlayerView pausedReason waitingKeepUp playProgress: 0.46012089206435497 bufferProgress:0.4208587349046713
PlayerView pausedReason waitingKeepUp playProgress: 0.49938373522825824 bufferProgress:0.46012115093387185
PlayerView pausedReason waitingKeepUp playProgress: 0.5386465783921615 bufferProgress:0.46012115093387185
PlayerView pausedReason waitingKeepUp playProgress: 0.5779094215560647 bufferProgress:0.46012115093387185
PlayerView pausedReason waitingKeepUp playProgress: 0.5935658499333412 bufferProgress:0.5977895779132529
PlayerView pausedReason waitingKeepUp playProgress: 0.632330835242496 bufferProgress:0.6372995379179125
PlayerView pausedReason waitingKeepUp playProgress: 0.6715945067888531 bufferProgress:0.6715965130276085
PlayerView pausedReason waitingKeepUp playProgress: 0.7120990952510386 bufferProgress:0.7121015027375451
PlayerView pausedReason waitingKeepUp playProgress: 0.7513635951798497 bufferProgress:0.7513635951798497
PlayerView pausedReason waitingKeepUp playProgress: 0.7889878978500887 bufferProgress:0.7936114239490546
PlayerView pausedReason waitingKeepUp playProgress: 0.8215408431380163 bufferProgress:0.8607104027088106
PlayerView pausedReason waitingKeepUp playProgress: 0.8570767936421647 bufferProgress:0.9178687919729741
PlayerView pausedReason waitingKeepUp playProgress: 0.9281470378855539 bufferProgress:0.9327796761418088

I hope this information will help you fix this issue ASAP.

Question about caching

Hi, I wanted to ask you if the videos that are downloaded are saved to disk. So if a video is downloaded once it won't be downloaded again?

After paused how to play video from first frame with 0 replay count and 0 watch duration?

Step 1 Play Video 1
Step 2 Paused Video 1
Step 3 Play video 2
Step 4 Paused Video 2 and play Video 1 with zero seek with zero repeats count and zero watch duration.

Current behaviors Right now Step 4 on Video 1 play with last paused duration onward with watch duration and repeat count.

We need how to play the video1 with zero seek with zero repeat count and zero watch duration

Can you set the amount of cache?

Can you set the amount of cache for videos? Or is it unlimited until you clear it?

If there is a set amount of cache, how big is it?

Usage with SwiftUI

Is it possible to use this library with SwiftUI? If so, could someone help out with a guide? Thanks.

expose helper to cancel download

    override func prepareForReuse() {

        super.prepareForReuse()

  playerView.player?.currentItem?.asset.cancelLoading()

}

should be just
playerView.cancelLoading()

or did I miss something?

Screen Shot 2021-04-02 at 9 45 14 pm

Video Load Problem

Video is loading slow(buffer slow) if we scroll tableview. I am getting error mention below -

[tcp] tcp_output [C39.1:2] flags=[R.] seq=700000644, ack=138727116, win=0 state=CLOSED rcv_nxt=138727116, snd_una=700000643

-[AVAssetResourceLoadingRequest finishLoading] was sent to an instance of AVAssetResourceLoadingRequest that was already finished. Ignoring.

Is there any way to play video immediate without stuck, while scrolling.

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.