Rupert  Beatty

Rupert Beatty

1668081540

A Simple Library That Lets You Play Sounds with A Single Line Of Code

SwiftySound

Overview

SwiftySound is a simple library that lets you deal with Swift sounds easily.

Static methods

Sound.play(file: "dog.wav")
Sound.play(url: fileURL)

More advanced example:

Sound.play(file: "dog", fileExtension: "wav", numberOfLoops: 2)

The above will play the sound three times.

Specify a negative number of loops to play the sound continously in an infinite loop:

Sound.play(file: "dog", fileExtension: "wav", numberOfLoops: -1)

Stop currently playing sounds:

Sound.stopAll()

Enable/disable all sounds:

Sound.enabled = true
Sound.enabled = false

The value of Sound.enabled property will be automatically persisted in UserDefaults and restored on the next launch of your app.

Change sound categories. SwiftySound provides a simple way of changing sound category:

Sound.category = .ambient

This changes the category of the underlying shared AVAudioSession instance. The default value is SoundCategory.ambient. Due to AVAudioSession architecture, this property is not available on macOS.

Creating instances of Sound class

You can also create an instance of a Sound class and store it somewhere in your app.

let mySound = Sound(url: fileURL)
mySound.play()

Creating an instance has more benefits like the ability to adjust the volume and playback callbacks.

Change the volume

You can change the volume of each Sound instance.

mySound.volume = 0.5

The value of volume property should be between 0.0 and 1.0, where 1.0 is the maximum.

Callbacks

You can pass a callback to the play method. It will be played after the sound finished playing. For looped sounds, the callback will be called once after the last loop has been played.

mySound.play { completed in
    print("completed: \(completed)")
}

The callback is not called if the sound was stopped, interrupted or in case of a playback error.

Features

  •  Playing single sounds
  •  Loops
  •  Infinite loops
  •  Playing the same sound multiple times simultaneously
  •  Stopping all sounds with a global static method
  •  Ability to pause and resume
  •  Adjusting sound volume
  •  Callbacks
  •  Global static variable to enable/disable all sounds

Requirements

  • Swift 5
  • Xcode 10.2 or later
  • iOS 8.0 or later
  • tvOS 9.0 or later
  • macOS 10.9 or later

For Xcode 8 and Swift 3 support, please use SwiftySound version 0.7.0. For Xcode 9 and Swift 4 support, please use SwiftySound version 1.0.0.

Installation

Installation with CocoaPods

CocoaPods is a dependency manager which automates and simplifies the process of using third-party libraries in your projects. See the Get Started section for more details.

Podfile

platform :ios, '8.0'
use_frameworks!
pod 'SwiftySound'

Installation with Carthage

Carthage is a lightweight dependency manager for Swift and Objective-C. It leverages CocoaTouch modules and is less invasive than CocoaPods.

To install with carthage, follow the instruction on Carthage

Cartfile

github "adamcichy/SwiftySound"

Installation with Swift Package Manager

The Swift Package Manager is a tool for managing the distribution of Swift code. Just add the url of this repo to your Package.swift file as a dependency:

import PackageDescription

let package = Package(
    name: "YourPackage",
    dependencies: [
        .Package(url: "https://github.com/adamcichy/SwiftySound.git",
                 majorVersion: 0)
    ]
)

Then run swift build and wait for SPM to install SwiftySound.

Manual installation

Drop the Sound.swift file into your project, link against AVFoundation.framework and you are ready to go.

Download Details:

Author: Adamcichy
Source Code: https://github.com/adamcichy/SwiftySound 
License: MIT license

#swift #audio #macos #ios #players 

A Simple Library That Lets You Play Sounds with A Single Line Of Code
Rupert  Beatty

Rupert Beatty

1667095020

A Video Player for IOS, Based on AVPlayer, Support The Horizontal

BMPlayer

A video player for iOS, based on AVPlayer, support the horizontal, vertical screen. support adjust volume, brightness and seek by slide, support subtitles.

中文说明

Features

  •  Support for horizontal and vertical play mode
  •  Support play online URL and local file
  •  Adjust brightness by slide vertical at left side of screen
  •  Adjust volume by slide vertical at right side of screen
  •  Slide horizontal to fast forward and rewind
  •  Support multi-definition video
  •  Custom playrate
  •  Add Http header and other options to AVURLAsset
  •  Easy to customize
  •  Supporting show local and online subtitles
  •  Swift 5

Requirements

  • iOS 10.0+
  • Xcode 10.0+
  • Swift 4+

Supporting the project

You can support the project by checking out our sponsor page. It takes only one click:

Sponsor banner 
This advert was placed by GitAds 

Installation

CocoaPods

Swiftpodfile
Swift 5.0pod 'BMPlayer', '~> 1.3.0'
Swift 4.2pod 'BMPlayer', '~> 1.2.0'
Swift 4.0pod 'BMPlayer', '~> 1.0.0'
Swift 3.0pod 'BMPlayer', '~> 0.9.1'
Swift 2.2pod 'BMPlayer', '~> 0.3.3'

To test the experimental caching support with VIMediaCache, use

pod 'BMPlayer/CacheSupport', :git => 'https://github.com/BrikerMan/BMPlayer.git'

Carthage

Add BMPlayer in your Cartfile.

github "BrikerMan/BMPlayer"

Run carthage to build the framework and drag the built BMPlayer.framework into your Xcode project.

Demo

run pod install at Example folder before run the demo.

Usage (Support IB and code)

Set status bar color

Please add the View controller-based status bar appearance field in info.plist and change it to NO

IB usage

Direct drag IB to UIView, the aspect ratio for the 16:9 constraint (priority to 750, lower than the 1000 line), the code section only needs to achieve. See more detail on the demo.

import BMPlayer

player.playWithURL(URL(string: url)!)

player.backBlock = { [unowned self] (isFullScreen) in
    if isFullScreen == true { return }
    let _ = self.navigationController?.popViewController(animated: true)
}

Code implementation by SnapKit

import BMPlayer

player = BMPlayer()
view.addSubview(player)
player.snp.makeConstraints { (make) in
    make.top.equalTo(self.view).offset(20)
    make.left.right.equalTo(self.view)
    // Note here, the aspect ratio 16:9 priority is lower than 1000 on the line, because the 4S iPhone aspect ratio is not 16:9
    make.height.equalTo(player.snp.width).multipliedBy(9.0/16.0).priority(750)
}
// Back button event
player.backBlock = { [unowned self] (isFullScreen) in
    if isFullScreen == true { return }
    let _ = self.navigationController?.popViewController(animated: true)
}

Set video url

let asset = BMPlayerResource(url: URL(string: "http://baobab.wdjcdn.com/14525705791193.mp4")!,
                             name: "风格互换:原来你我相爱")
player.setVideo(resource: asset)

multi-definition video with cover

let res0 = BMPlayerResourceDefinition(url: URL(string: "http://baobab.wdjcdn.com/1457162012752491010143.mp4")!,
                                      definition: "高清")
let res1 = BMPlayerResourceDefinition(url: URL(string: "http://baobab.wdjcdn.com/1457162012752491010143.mp4")!,
                                      definition: "标清")

let asset = BMPlayerResource(name: "周末号外丨中国第一高楼",
                             definitions: [res0, res1],
                             cover: URL(string: "http://img.wdjimg.com/image/video/447f973848167ee5e44b67c8d4df9839_0_0.jpeg"))

player.setVideo(resource: asset)

Add HTTP header for request

let header = ["User-Agent":"BMPlayer"]
let options = ["AVURLAssetHTTPHeaderFieldsKey":header]

let definition = BMPlayerResourceDefinition(url: URL(string: "http://baobab.wdjcdn.com/1457162012752491010143.mp4")!,
                                            definition: "高清",
                                            options: options)

let asset = BMPlayerResource(name: "Video Name",
                             definitions: [definition])

Listening to player state changes

See more detail from the Example project

Block

//Listen to when the player is playing or stopped
player?.playStateDidChange = { (isPlaying: Bool) in
    print("playStateDidChange \(isPlaying)")
}

//Listen to when the play time changes
player?.playTimeDidChange = { (currentTime: TimeInterval, totalTime: TimeInterval) in
    print("playTimeDidChange currentTime: \(currentTime) totalTime: \(totalTime)")
}

Delegate

protocol BMPlayerDelegate {
    func bmPlayer(player: BMPlayer ,playerStateDidChange state: BMPlayerState) { }
    func bmPlayer(player: BMPlayer ,loadedTimeDidChange loadedDuration: TimeInterval, totalDuration: TimeInterval)  { }
    func bmPlayer(player: BMPlayer ,playTimeDidChange currentTime : TimeInterval, totalTime: TimeInterval)  { }
    func bmPlayer(player: BMPlayer ,playerIsPlaying playing: Bool)  { }
}

Customize player

Needs to change before the player alloc.

// should print log, default false
BMPlayerConf.allowLog = false
// should auto play, default true
BMPlayerConf.shouldAutoPlay = true
// main tint color, default whiteColor
BMPlayerConf.tintColor = UIColor.whiteColor()
// options to show header view (which include the back button, title and definition change button) , default .Always,options: .Always, .HorizantalOnly and .None
BMPlayerConf.topBarShowInCase = .Always
// loader type, see detail:https://github.com/ninjaprox/NVActivityIndicatorView
BMPlayerConf.loaderType  = NVActivityIndicatorType.BallRotateChase
// enable setting the brightness by touch gesture in the player
BMPlayerConf.enableBrightnessGestures = true
// enable setting the volume by touch gesture in the player
BMPlayerConf.enableVolumeGestures = true
// enable setting the playtime by touch gesture in the player
BMPlayerConf.enablePlaytimeGestures = true

Advanced Customize

  • Subclass BMPlayerControlView to create your personal control UI, check the Example.
  • Use the BMPlayerLayer with your own player control view.

Demonstration

gif

Reference:

This project heavily reference the Objective-C version of this project ZFPlayer, thanks for the generous help of ZFPlayer's author.

Contact me:

Contributors

You are welcome to fork and submit pull requests.

Download Details:

Author: BrikerMan
Source Code: https://github.com/BrikerMan/BMPlayer 
License: MIT license

#swift #video #players 

A Video Player for IOS, Based on AVPlayer, Support The Horizontal
Rupert  Beatty

Rupert Beatty

1667013960

Video Player in Swift, Simple Way to Play and Stream Media on iOS/tvOS

Player

Player is a simple iOS video player library written in Swift.

Need a different version of Swift?

  • 5.0 - Target your Podfile to the latest release or master
  • 4.2 - Target your Podfile to the swift4.2 branch
  • 4.0 - Target your Podfile to the swift4.0 branch

Features

  •  plays local media or streams remote media over HTTP
  •  customizable UI and user interaction
  •  no size restrictions
  •  orientation change support
  •  simple API
  •  video frame snapshot support

Quick Start

Player is available for installation using the Cocoa dependency manager CocoaPods. Alternatively, you can simply copy the Player.swift file into your Xcode project.

# CocoaPods
pod "Player", "~> 0.13.2"

# Carthage
github "piemonte/Player" ~> 0.13.2

Usage

The sample project provides an example of how to integrate Player, otherwise you can follow these steps.

Allocate and add the Player controller to your view hierarchy.

 self.player = Player()
 self.player.playerDelegate = self
 self.player.playbackDelegate = self
 self.player.view.frame = self.view.bounds

 self.addChild(self.player)
 self.view.addSubview(self.player.view)
 self.player.didMove(toParent: self)

Provide the file path to the resource you would like to play locally or stream. Ensure you're including the file extension.

let videoUrl: URL = // file or http url
self.player.url = videoUrl

play/pause

 self.player.playFromBeginning()

Adjust the fill mode for the video, if needed.

 self.player.fillMode = .resizeAspectFit

Display video playback progress, if needed.

extension ViewController: PlayerPlaybackDelegate {

    public func playerPlaybackWillStartFromBeginning(_ player: Player) {
    }

    public func playerPlaybackDidEnd(_ player: Player) {
    }

    public func playerCurrentTimeDidChange(_ player: Player) {
        let fraction = Double(player.currentTime) / Double(player.maximumDuration)
        self._playbackViewController?.setProgress(progress: CGFloat(fraction), animated: true)
    }

    public func playerPlaybackWillLoop(_ player: Player) {
        self. _playbackViewController?.reset()
    }

}

Documentation

You can find the docs here. Documentation is generated with jazzy and hosted on GitHub-Pages.

Community

Resources

Download Details:

Author: Piemonte
Source Code: https://github.com/piemonte/Player 
License: MIT license

#swift #ios #players #stream 

Video Player in Swift, Simple Way to Play and Stream Media on iOS/tvOS
Rupert  Beatty

Rupert Beatty

1666515720

A Powerful and Completely Customizable Media Player for iOS

MobilePlayer 

A powerful and completely customizable media player for iOS.

introduction

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

CocoaPods

Add the following line in your Podfile.

pod "MobilePlayer"

Carthage

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.

Download Details:

Author: sahin
Source Code: https://github.com/sahin/mobileplayer-ios 
License: View license

#swift #ios #players #mobile 

A Powerful and Completely Customizable Media Player for iOS

Lossless-cut: The Swiss Army Knife Of Lossless Video/audio Editing

LosslessCut

The swiss army knife of lossless video/audio editing

screenshot

LosslessCut aims to be the ultimate cross platform FFmpeg GUI for extremely fast and lossless operations on video, audio, subtitle and other related media files. The main feature is lossless trimming and cutting of video and audio files, which is great for saving space by rough-cutting your large video files taken from a video camera, GoPro, drone, etc. It lets you quickly extract the good parts from your videos and discard many gigabytes of data without doing a slow re-encode and thereby losing quality. Or you can add a music or subtitle track to your video without needing to encode. Everything is extremely fast because it does an almost direct data copy, fueled by the awesome FFmpeg which does all the grunt work.

Features

  • Lossless cutting of most video and audio formats
  • Smart cut (experimental)
  • Losslessly cut out parts of video/audio (for cutting away commercials etc.)
  • Losslessly rearrange the order of video/audio segments
  • Lossless merge/concatenation of arbitrary files (with identical codecs parameters, e.g. from the same camera)
  • Lossless stream editing
    • Combine arbitrary tracks from multiple files (ex. add music or subtitle track to a video file)
    • Remove unneeded tracks
    • Replace or re-encode only some tracks
    • Extract all tracks from a file (extract video, audio, subtitle, attachments and other tracks from one file into separate files)
  • Batch view for fast multi-file workflow
  • Keyboard shortcut workflow
  • Losslessly remux video/audio into a different container (file) format
  • Take full-resolution snapshots from videos in JPEG/PNG format, or export ranges of video frames to images
  • Manual input of cutpoint times
  • Apply a per-file timecode offset (and auto load timecode from file)
  • Edit file metadata, per-track metadata and per-track disposition
  • Change rotation/orientation metadata in videos
  • View technical data about all tracks
  • Timeline zoom and frame/keyframe jumping for cutting around keyframes
  • Video thumbnails and audio waveform
  • Saves per project cut segments to project file
  • View FFmpeg last command log so you can modify and re-run recent commands on the command line
  • Undo/redo
  • Give labels to cut segments
  • Annotate segments with tags
  • Import/export segments: MP4/MKV chapter marks, Text file, YouTube, CSV, CUE, XML (DaVinci, Final Cut Pro) and more
  • MKV/MP4 embedded chapters marks editor
  • View subtitles
  • Customizable keyboard hotkeys
  • Black scene detection
  • Divide timeline into segments with length L or into N segments or even randomized segments!

Example lossless use cases

  • Cut out commercials from a recorded TV show (and re-format from TS to MP4)
  • Remove audio tracks from a file
  • Extract music track from a video and cut it to your needs
  • Add music to a video (or replace existing audio track)
  • Combine audio and video tracks from separate recordings
  • Include an external subtitle into a video
  • Quickly change a H264/H265 MKV video to MOV or MP4 for playback on iPhone
  • Import a list of cut times from other tool as a EDL (edit decision list, CSV) and run these cuts with LosslessCut
  • Export a list of cut times as a CSV EDL and process these in another tool
  • Quickly cut a file by its MP4/MKV chapters
  • Quickly cut a YouTube video by its chapters (or music times from a comment)
  • Change the language of a file's audio/subtitle tracks
  • Attach cover art to videos
  • Change author, title, GPS position, recording time of a video
  • Fix rotation of a video that has the wrong orientation flag set
    • Great for rotating phone videos that come out the wrong way without actually re-encoding the video.
  • Loop a video / audio clip X times quickly without re-encoding
  • Convert a video or parts of it into X image files (not lossless)

Export cut times as YouTube Chapters

  1. Export with Merge and "Create chapters from merged segments" enabled
  2. Open the exported file and select "Import chapters" in the dialog
  3. File -> Export project -> YouTube Chapters

Re-encode only the audio track, keeping the lossless video track

First export each track as individual files. Then use Handbrake or similar to re-encode the audio file. Then use the Tools->Merge in LosslessCut to merge the original video stream with your Handbrake output (or drag it into your original LosslessCut video to include it as a new track.)

Advanced multi-step workflows

Tip: you can use LosslessCut in multiple passes in order to achieve separate trimming of individual tracks:

  1. Open a file an export all tracks as individual files
  2. Open the exported track files independently and cut them as desired
  3. Add the track back to the video and combine them to one output video

Download

If you want to support my continued work on LosslessCut, and you want the advantage of a secure and simple installation process with automatic updates, consider getting it from your favorite store:

 MS badge Mac App Store MS badge Snapcraft

If you prefer to download the executables manually, this will of course always be free:

If you find LosslessCut useful, I'm very thankful for donations.

Difference between App Stores and Github download

They have exactly the same in-app features, except for a few platform limitations. Apple doesn't allow opening VOB files with App Store apps. Apple App Store apps need to prompt for output directory. LosslessCut version in the App Stores is a few versions behind the GitHub version, because I want to be sure that the new versions work perfectly before releasing in the App Stores. GitHub version can contain new, untested features and may contain some bugs. I consider the newest GitHub versions to be a public "beta" test.

Supported formats

Since LosslessCut is based on Chromium and uses the HTML5 video player, not all FFmpeg supported formats will be supported smoothly. The following formats/codecs should generally work: MP4, MOV, WebM, MKV, OGG, WAV, MP3, AAC, H264, Theora, VP8, VP9 For more information about supported formats / codecs, see https://www.chromium.org/audio-video.

Unsupported files can still be converted to a supported format/codec from the File menu. (Try the "fastest" option first.) A low quality version of the file (with/without audio) will then be created and opened in the player. The actual cut/export operation will still be performed on the original file, so it will be lossless. This allows for potentially opening any file that FFmpeg is able to decode.

Video demos

Common features

How to add a thumbnail to an MP4

How to add multi-language audio to a video

Your video here? If you would like to make a video showing off LosslessCut use cases, let me know and I can link it here!

Typical workflow

  • Drag drop a video file into player or use ⌘/CTRL+O.
  • Press SPACE to play/pause or ◀▶, ,. or mouse/trackpad wheel to seek back/forth.
  • Select the cut segment's start and end time by moving the time marker and then pressing I to set start time, and O to set end time.
    • Note that all segments you create will be preserved and exported as new files. You can change this behavior with the Yin Yang symbol ☯️, in which case it will instead remove all selected segments and export the parts between segments.
    • Note also that start times will not be accurate, see Known issues
  • (optional) If you want to add more than one segment, move to the desired start time and press +, then select the next segment start/end times with I/O.
  • (optional) If you want to re-merge all the selected segments into one file after cutting, toggle the button Separate files to Merge cuts.
  • (optional) If you want to export to a certain output folder, press the Working dir unset button (default: Input file folder)
  • (optional) If you want to change orientation, press the rotation button
  • (optional) By default, audio, video and subtitle tracks from the input file will be cut and exported. Press the Tracks button to customise and/or add new tracks from other files.
  • (optional) select a new output format
  • (optional) In the right-hand segments panel, right click a segment for options, or drag-drop to reorder. Segments will appear in this order in the merged output.
  • When done, press the Export button (or E) to show an overview with export options.
  • (optional) adjust any export options
  • Then press Export again to confirm the export
  • Press the Camera button (or C) if you want to take a JPEG/PNG snapshot from the current time
  • If you want to move the original file to trash, press the trash button
  • For best results you may need to trial and error with another output format (Matroska takes nearly everything), change keyframe cut mode or disable some tracks (see known issues below).
  • Press H to view help and all keyboard shortcuts.
  • Note: The original video file will not be modified. Instead, a file is created file in the same directory as the original file with from/to timestamps in the file name.

Known issues & limitations

  • Cutting times are not accurate! Start cut time will be "rounded" to the nearest previous keyframe. This means that you often have move the start cut time to few frames after the desired keyframe.
    • Lossless cutting is not an exact science. For some files, it just works. For others, you may need to trial and error depending on the codec, keyframes etc to get the best cut. See #330
    • Your mileage may vary when it comes to Keyframe cut vs Normal cut. You may need to try both, depending on the video. ffmpeg also has documentation about these two seek/cut modes. Keyframe cut means -ss before -i and Normal cut means -ss after -i.
    • You may try to enable the new "Smart cut" mode. However it is very experimental and may not work for most files.
  • When exporting you may lose some proprietary data tracks (like tmcd, fdsc and gpmd added by GoPro). These can however be losslessly exported to separate files.
  • EXIF/metadata can be preserved (see Export Options dialog), but it doesn't always output compliant files, so use it carefully.
  • Some codecs are not natively supported, but will preview with low quality playback and no audio. You may convert these files to a supported codec from the File menu, see #88.

Troubleshooting / FAQ

  • Can LosslessCut crop, resize, stretch, mirror, overlay text/images, watermark, blur, redact, re-encode, speed-up/slow-down, create GIF, slideshow, burn subtitles, color grading, fade/combine/mix audio tracks?
  • Can LosslessCut be batched/automated using a CLI or API?
    • No, it was never designed for that. However there are a few feature requests regarding this: #980 #868
  • MPEG TS files have a tendency to be a bit problematic. It may help to first remux them to another format like MP4/MKV. Then you can open the MP4/MKV file an work on that.
  • Linux: If you get an error like FATAL:setuid_sandbox_host.cc(157)] The SUID sandbox helper binary was found, but is not configured correctly. Rather than run without sandboxing I'm aborting now., try to run it as ./lossless-cut --no-sandbox. See #258

Windows issues

  • What's the difference between .exe and .zip downloads? .exe will self-extract on startup to a temp folder and is therefore slower to start up. .zip must be extracted manually but is very fast to start up.
  • If you get an error when cutting or opening any kind of file, try to disable your anti-virus. See #18
  • How to uninstall LosslessCut? There is no installer. Just delete the EXE file or containing folder. User files are stored in your appData folder.
  • If the app crashes immediately upon startup, check the permissions of your User and Temp folders, see 61.
  • Completely white window when starting up? Try to run with --disable-gpu - See 781.

If any other problem, check Known issues, or please search for existing issues before you file an issue here on GitHub. You can check the developer tools for any errors or clues. Menu: Tools -> Toggle Developer Tools. Also you are welcome to hang out on Discord 🤗

CSV import/export

  • The CSV export/import function takes CSV files with one cut segment on each line. Each line contains three columns: segment start, segment end, label.
  • segment start and segment end are expressed in seconds or left empty. Empty segment end means segment ends at the duration of the video.
  • Use comma , to separate the fields (not semicolon ;)

example.csv

,56.9568,First segment starting at 0
70,842.33,"Another quoted label"
1234,,Last segment

Command line interface (CLI)

LosslessCut only has limited support for automation through the CLI. Note that these examples assume that you have set up LosslessCut in your PATH environment. Alternatively you can run it like this:

# First navigate to the folder containing the LosslessCut app
cd /path/to/directory/containing/app
# On Linux:
./LosslessCut arguments
# On Windows:
./LosslessCut.exe arguments
# On MacOS:
./LosslessCut.app/Contents/MacOS/LosslessCut arguments

Open one or more files:

LosslessCut file1.mp4 file2.mkv

Override settings (experimental)

See available settings. Note that this is subject to change in newer versions. ⚠️ If you specify incorrect values it could corrupt your configuration file. You may use JSON or JSON5:

LosslessCut --settings-json '{captureFormat:"jpeg", "keyframeCut":true}'

Developing

See the developer notes.

Donate 🙈

This project is maintained by me alone. The project will always remain free and open source, but if it's useful for you, consider supporting me. :) It will give me extra motivation to improve it. Or even better donate to ffmpeg because they are doing the world a big favor 🙏

Paypal | crypto

Articles

Attributions

More software

  • I made a command line video editor with slick transitions and lots of colors! editly
  • I made a tool for cross platform sharing of files between computer/phone over the local network: ezshare
  • I created a super simple Instagram bot for getting more followers SimpleInstaBot

Made with ❤️ in 🇳🇴

More apps by mifi.no

Follow me on GitHub, YouTube, IG, Twitter for more awesome content!


Thanks to my supporters and everyone who purchased LosslessCut! 


Author: mifi
Source Code: https://github.com/mifi/lossless-cut 
License: GPL-2.0 license

#javascript #editor #players #video 

Lossless-cut: The Swiss Army Knife Of Lossless Video/audio Editing
Nat  Grady

Nat Grady

1657883160

LosslessCut: The Swiss Army Knife Of Lossless Video/audio Editing

LosslessCut

The swiss army knife of lossless video/audio editing    

screenshotLosslessCut aims to be the ultimate cross platform FFmpeg GUI for extremely fast and lossless operations on video, audio, subtitle and other related media files. The main feature is lossless trimming and cutting of video and audio files, which is great for saving space by rough-cutting your large video files taken from a video camera, GoPro, drone, etc. It lets you quickly extract the good parts from your videos and discard many gigabytes of data without doing a slow re-encode and thereby losing quality. Or you can add a music or subtitle track to your video without needing to encode. Everything is extremely fast because it does an almost direct data copy, fueled by the awesome FFmpeg which does all the grunt work.

Features

  • Lossless cutting of most video and audio formats
  • Smart cut (experimental)
  • Losslessly cut out parts of video/audio (for cutting away commercials etc.)
  • Losslessly rearrange the order of video/audio segments
  • Lossless merge/concatenation of arbitrary files (with identical codecs parameters, e.g. from the same camera)
  • Lossless stream editing
    • Combine arbitrary tracks from multiple files (ex. add music or subtitle track to a video file)
    • Remove unneeded tracks
    • Replace or re-encode only some tracks
    • Extract all tracks from a file (extract video, audio, subtitle, attachments and other tracks from one file into separate files)
  • Batch view for fast multi-file workflow
  • Keyboard shortcut workflow
  • Losslessly remux video/audio into a different container (file) format
  • Take full-resolution snapshots from videos in JPEG/PNG format, or export ranges of video frames to images
  • Manual input of cutpoint times
  • Apply a per-file timecode offset (and auto load timecode from file)
  • Edit file metadata, per-track metadata and per-track disposition
  • Change rotation/orientation metadata in videos
  • View technical data about all tracks
  • Timeline zoom and frame/keyframe jumping for cutting around keyframes
  • Video thumbnails and audio waveform
  • Saves per project cut segments to project file
  • View FFmpeg last command log so you can modify and re-run recent commands on the command line
  • Undo/redo
  • Give labels to cut segments
  • Annotate segments with tags
  • Import/export segments: MP4/MKV chapter marks, Text file, YouTube, CSV, CUE, XML (DaVinci, Final Cut Pro) and more
  • MKV/MP4 embedded chapters marks editor
  • View subtitles
  • Customizable keyboard hotkeys
  • Black scene detection
  • Divide timeline into segments with length L or into N segments or even randomized segments!

Example lossless use cases

  • Cut out commercials from a recorded TV show (and re-format from TS to MP4)
  • Remove audio tracks from a file
  • Extract music track from a video and cut it to your needs
  • Add music to a video (or replace existing audio track)
  • Combine audio and video tracks from separate recordings
  • Include an external subtitle into a video
  • Quickly change a H264/H265 MKV video to MOV or MP4 for playback on iPhone
  • Import a list of cut times from other tool as a EDL (edit decision list, CSV) and run these cuts with LosslessCut
  • Export a list of cut times as a CSV EDL and process these in another tool
  • Quickly cut a file by its MP4/MKV chapters
  • Quickly cut a YouTube video by its chapters (or music times from a comment)
  • Change the language of a file's audio/subtitle tracks
  • Attach cover art to videos
  • Change author, title, GPS position, recording time of a video
  • Fix rotation of a video that has the wrong orientation flag set
    • Great for rotating phone videos that come out the wrong way without actually re-encoding the video.
  • Loop a video / audio clip X times quickly without re-encoding
  • Convert a video or parts of it into X image files (not lossless)

Export cut times as YouTube Chapters

  1. Export with Merge and "Create chapters from merged segments" enabled
  2. Open the exported file and select "Import chapters" in the dialog
  3. File -> Export project -> YouTube Chapters

Re-encode only the audio track, keeping the lossless video track

First export each track as individual files. Then use Handbrake or similar to re-encode the audio file. Then use the Tools->Merge in LosslessCut to merge the original video stream with your Handbrake output (or drag it into your original LosslessCut video to include it as a new track.)

Advanced multi-step workflows

Tip: you can use LosslessCut in multiple passes in order to achieve separate trimming of individual tracks:

  1. Open a file an export all tracks as individual files
  2. Open the exported track files independently and cut them as desired
  3. Add the track back to the video and combine them to one output video

Download

If you want to support my continued work on LosslessCut, and you want the advantage of a secure and simple installation process with automatic updates, consider getting it from your favorite store:

Mac App Store MS badge Snapcraft

If you prefer to download the executables manually, this will of course always be free:

If you find LosslessCut useful, I'm very thankful for donations.

Difference between App Stores and Github download

They have exactly the same in-app features, except for a few platform limitations. Apple doesn't allow opening VOB files with App Store apps. Apple App Store apps need to prompt for output directory. LosslessCut version in the App Stores is a few versions behind the GitHub version, because I want to be sure that the new versions work perfectly before releasing in the App Stores. GitHub version can contain new, untested features and may contain some bugs. I consider the newest GitHub versions to be a public "beta" test.

Supported formats

Since LosslessCut is based on Chromium and uses the HTML5 video player, not all FFmpeg supported formats will be supported smoothly. The following formats/codecs should generally work: MP4, MOV, WebM, MKV, OGG, WAV, MP3, AAC, H264, Theora, VP8, VP9 For more information about supported formats / codecs, see https://www.chromium.org/audio-video.

Unsupported files can still be converted to a supported format/codec from the File menu. (Try the "fastest" option first.) A low quality version of the file (with/without audio) will then be created and opened in the player. The actual cut/export operation will still be performed on the original file, so it will be lossless. This allows for potentially opening any file that FFmpeg is able to decode.

Video demos

Common features

How to add a thumbnail to an MP4

How to add multi-language audio to a video

Your video here? If you would like to make a video showing off LosslessCut use cases, let me know and I can link it here!

Typical workflow

  • Drag drop a video file into player or use ⌘/CTRL+O.
  • Press SPACE to play/pause or ◀▶, ,. or mouse/trackpad wheel to seek back/forth.
  • Select the cut segment's start and end time by moving the time marker and then pressing I to set start time, and O to set end time.
    • Note that all segments you create will be preserved and exported as new files. You can change this behavior with the Yin Yang symbol ☯️, in which case it will instead remove all selected segments and export the parts between segments.
    • Note also that start times will not be accurate, see Known issues
  • (optional) If you want to add more than one segment, move to the desired start time and press +, then select the next segment start/end times with I/O.
  • (optional) If you want to re-merge all the selected segments into one file after cutting, toggle the button Separate files to Merge cuts.
  • (optional) If you want to export to a certain output folder, press the Working dir unset button (default: Input file folder)
  • (optional) If you want to change orientation, press the rotation button
  • (optional) By default, audio, video and subtitle tracks from the input file will be cut and exported. Press the Tracks button to customise and/or add new tracks from other files.
  • (optional) select a new output format
  • (optional) In the right-hand segments panel, right click a segment for options, or drag-drop to reorder. Segments will appear in this order in the merged output.
  • When done, press the Export button (or E) to show an overview with export options.
  • (optional) adjust any export options
  • Then press Export again to confirm the export
  • Press the Camera button (or C) if you want to take a JPEG/PNG snapshot from the current time
  • If you want to move the original file to trash, press the trash button
  • For best results you may need to trial and error with another output format (Matroska takes nearly everything), change keyframe cut mode or disable some tracks (see known issues below).
  • Press H to view help and all keyboard shortcuts.
  • Note: The original video file will not be modified. Instead, a file is created file in the same directory as the original file with from/to timestamps in the file name.

Known issues & limitations

  • Cutting times are not accurate! Start cut time will be "rounded" to the nearest previous keyframe. This means that you often have move the start cut time to few frames after the desired keyframe.
    • Lossless cutting is not an exact science. For some files, it just works. For others, you may need to trial and error depending on the codec, keyframes etc to get the best cut. See #330
    • Your mileage may vary when it comes to Keyframe cut vs Normal cut. You may need to try both, depending on the video. ffmpeg also has documentation about these two seek/cut modes. Keyframe cut means -ss before -i and Normal cut means -ss after -i.
    • You may try to enable the new "Smart cut" mode. However it is very experimental and may not work for most files.
  • When exporting you may lose some proprietary data tracks (like tmcd, fdsc and gpmd added by GoPro). These can however be losslessly exported to separate files.
  • EXIF/metadata can be preserved (see Export Options dialog), but it doesn't always output compliant files, so use it carefully.
  • Some codecs are not natively supported, but will preview with low quality playback and no audio. You may convert these files to a supported codec from the File menu, see #88.

Troubleshooting / FAQ

  • Can LosslessCut crop, resize, stretch, mirror, overlay text/images, watermark, blur, redact, re-encode, speed-up/slow-down, create GIF, slideshow, burn subtitles, color grading, fade/combine/mix audio tracks?
  • MPEG TS files have a tendency to be a bit problematic. It may help to first remux them to another format like MP4/MKV. Then you can open the MP4/MKV file an work on that.
  • Linux: If you get an error like FATAL:setuid_sandbox_host.cc(157)] The SUID sandbox helper binary was found, but is not configured correctly. Rather than run without sandboxing I'm aborting now., try to run it as ./lossless-cut --no-sandbox. See #258

Windows issues

  • What's the difference between .exe and .zip downloads? .exe will self-extract on startup to a temp folder and is therefore slower to start up. .zip must be extracted manually but is very fast to start up.
  • If you get an error when cutting or opening any kind of file, try to disable your anti-virus. See #18
  • How to uninstall LosslessCut? There is no installer. Just delete the EXE file or containing folder. User files are stored in your appData folder.
  • If the app crashes immediately upon startup, check the permissions of your User and Temp folders, see 61.
  • Completely white window when starting up? Try to run with --disable-gpu - See 781.

If any other problem, check Known issues, or please search for existing issues before you file an issue here on GitHub. You can check the developer tools for any errors or clues. Menu: Tools -> Toggle Developer Tools. Also you are welcome to hang out on Discord 🤗

CSV import/export

  • The CSV export/import function takes CSV files with one cut segment on each line. Each line contains three columns: segment start, segment end, label.
  • segment start and segment end are expressed in seconds or left empty. Empty segment end means segment ends at the duration of the video.
  • Use comma , to separate the fields (not semicolon ;)

example.csv

,56.9568,First segment starting at 0
70,842.33,"Another quoted label"
1234,,Last segment

Command line interface (CLI)

Note that these exampels assume that you have set up LosslessCut in your PATH environment. Alternatively you can run it like this:

# First navigate to the folder containing the LosslessCut app
cd /path/to/directory/containing/app
# On Linux:
./LosslessCut arguments
# On Windows:
./LosslessCut.exe arguments
# On MacOS:
./LosslessCut.app/Contents/MacOS/LosslessCut arguments

Open one or more files:

LosslessCut file1.mp4 file2.mkv

Override settings (experimental)

See available settings. Note that this is subject to change in newer versions. ⚠️ If you specify incorrect values it could corrupt your configuration file. You may use JSON or JSON5:

LosslessCut --settings-json '{captureFormat:"jpeg", "keyframeCut":true}'

Developing

See the developer notes.

Donate 🙈

This project is maintained by me alone. The project will always remain free and open source, but if it's useful for you, consider supporting me. :) It will give me extra motivation to improve it. Or even better donate to ffmpeg because they are doing the world a big favor 🙏

Paypal | crypto

Articles

Attributions

More software

  • I made a command line video editor with slick transitions and lots of colors! editly
  • I made a tool for cross platform sharing of files between computer/phone over the local network: ezshare
  • I created a super simple Instagram bot for getting more followers SimpleInstaBot

Made with ❤️ in 🇳🇴

More apps by mifi.no

Follow me on GitHub, YouTube, IG, Twitter for more awesome content!

Thanks to my supporters and everyone who purchased LosslessCut! 

Author: Mifi
Source Code: https://github.com/mifi/lossless-cut 
License: GPL-2.0 license

 #electron #editor #players #javascript 

LosslessCut: The Swiss Army Knife Of Lossless Video/audio Editing
Mike  Kozey

Mike Kozey

1655362860

Pod_player: Video Player for Flutter Web & Mobile Devices, Play Video

Video player for flutter web & mobile devices, pod player supports playing video from `Youtube` and `Vimeo`

pod player is a simple and easy-to-use video player. Its video controls are similar to Youtube player (with customizable controls) and also can play videos from Youtube and Vimeo (By providing url/video_id).

This plugin built upon flutter's official video_player plugin


PLATFORMAVAILABLE
Android
IOS
WEB

Features

  • Play youtube videos (using video URL or ID)
  • Play vimeo videos (using video ID)
  • Video overlay similar to youtube
  • Double tap to seek video.
  • On video tap show/hide video overlay.
  • Auto hide overlay
  • Change playback speed
  • Custom overlay
  • Custom progress bar
  • Change video quality (for vimeo and youtube)
  • Enable/disable fullscreen player
  • [TODO] support for live youtube video
  • [TODO] support for video playlist

Features on web

Double tap on Video player to enable/disable fullscreen

Mute/unmute volume

Video player integration with keyboard

  • SPACE play/pause video
  • M mute/unMute video
  • F enable/disable fullscreen
  • ESC enable/disable fullscreen
  • -> seek video forward
  • <- seek video backward

Double tap on video (enable/diables fullscreen)

Demo


  • Playing videos from youtube

pod_player


  • Vimeo player and custom video player

Change quality and playback speedControl video from any where

  • Controls similar to youtube

with overlaywithout overlay (alwaysShowProgressBar = true)

  • On mobile full screen


  • Video controls

On Double tapCustom progress bar

  • Video player on web



pod_player

Usage

Installation


In your pubspec.yaml file within your Flutter Project:

dependencies:
  pod_player: <latest_version>

Android


If you are using network-based videos, ensure that the following permission is present in your Android Manifest file, located in <project root>/android/app/src/main/AndroidManifest.xml:

<uses-permission android:name="android.permission.INTERNET"/>

If you need to access videos using http (rather than https) URLs.

Located inside application tag

<application
  - - -
  - - - - - -
  android:usesCleartextTraffic="true"

Ios


Add permissions to your app's Info.plist file,

located in <project root>/ios/Runner/Info.plist

<key>NSAppTransportSecurity</key>
<dict>
  <key>NSAllowsArbitraryLoads</key>
  <true/>
</dict>

Web ( Not recommended in production)


if u are using youtube or vimeo player on web, then there will be some issue with CORS only in web, so use this flutter_cors package

using flutter_cors package to enable or disable CORS

To Enable CORS (run this command )

dart pub global activate flutter_cors
fluttercors --enable

To Disable CORS (run this command )

fluttercors --disable

How to use


import 'package:pod_player/pod_player.dart';
import 'package:flutter/material.dart';

class PlayVideoFromNetwork extends StatefulWidget {
  const PlayVideoFromNetwork({Key? key}) : super(key: key);

  @override
  State<PlayVideoFromNetwork> createState() => _PlayVideoFromNetworkState();
}

class _PlayVideoFromNetworkState extends State<PlayVideoFromNetwork> {
  late final PodPlayerController controller;
  @override
  void initState() {
    controller = PodPlayerController(
      playVideoFrom: PlayVideoFrom.network(
        'https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/ForBiggerFun.mp4',
      ),
    )..initialise();
    super.initState();
  }
  @override
  void dispose() {
    controller.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: PodVideoPlayer(controller: controller),
    );
  }
}

Configure pod player

controller = PodPlayerController(
      playVideoFrom: PlayVideoFrom.youtube('https://youtu.be/A3ltMaM6noM'),
      podPlayerConfig: const PodPlayerConfig(
          autoPlay: true,
          isLooping: false,
          initialVideoQuality: 360
        )
    )..initialise();

Add Thumbnail

PodVideoPlayer(
  controller: controller,
  videoThumbnail: const DecorationImage(
    /// load from asset: AssetImage('asset_path')
    image: NetworkImage('https://images.unsplash.com/photo-1569317002804-ab77bcf1bce4?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxzZWFyY2h8MXx8dW5zcGxhc2h8ZW58MHx8MHx8&w=1000&q=80',
    ),
    fit: BoxFit.cover,
  ),
),

How to play video from youtube


import 'package:pod_player/pod_player.dart';
import 'package:flutter/material.dart';

class PlayVideoFromYoutube extends StatefulWidget {
  const PlayVideoFromYoutube({Key? key}) : super(key: key);

  @override
  State<PlayVideoFromYoutube> createState() => _PlayVideoFromYoutubeState();
}

class _PlayVideoFromYoutubeState extends State<PlayVideoFromYoutube> {
  late final PodPlayerController controller;
  @override
  void initState() {
    controller = PodPlayerController(
      playVideoFrom: PlayVideoFrom.youtube('https://youtu.be/A3ltMaM6noM'),
    )..initialise();
    super.initState();
  }
  @override
  void dispose() {
    controller.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: PodVideoPlayer(controller: controller),
    );
  }
}

How to play video from vimeo


import 'package:pod_player/pod_player.dart';
import 'package:flutter/material.dart';

class PlayVideoFromVimeo extends StatefulWidget {
  const PlayVideoFromVimeo({Key? key}) : super(key: key);

  @override
  State<PlayVideoFromVimeo> createState() => _PlayVideoFromVimeoState();
}

class _PlayVideoFromVimeoState extends State<PlayVideoFromVimeo> {
  late final PodPlayerController controller;
  @override
  void initState() {
    controller = PodPlayerController(
      playVideoFrom: PlayVideoFrom.vimeo('518228118'),
    )..initialise();
    super.initState();
  }
  @override
  void dispose() {
    controller.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: PodVideoPlayer(controller: controller),
    );
  }
}

Options


  • Options for mobile

Normal player optionVimeo player optionChange quality of video

Example


Use this package as a library

Depend on it

Run this command:

With Flutter:

 $ flutter pub add pod_player

This will add a line like this to your package's pubspec.yaml (and run an implicit flutter pub get):

dependencies:
  pod_player: ^0.0.6

Alternatively, your editor might support flutter pub get. Check the docs for your editor to learn more.

Import it

Now in your Dart code, you can use:

import 'package:pod_player/pod_player.dart';

example/lib/main.dart

import 'package:example/screens/from_asset.dart';
import 'package:example/screens/from_network.dart';
import 'package:example/screens/from_network_urls.dart';
import 'package:example/screens/from_youtube.dart';
import 'package:flutter/material.dart';
import 'package:pod_player/pod_player.dart';

import 'screens/cutom_video_controllers.dart';
import 'screens/from_vimeo_id.dart';

void main() {
  PodVideoPlayer.enableLogs = true;
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      routes: {
        '/fromVimeoId': (context) => const PlayVideoFromVimeoId(),
        '/fromYoutube': (context) => const PlayVideoFromYoutube(),
        '/fromAsset': (context) => const PlayVideoFromAsset(),
        '/fromNetwork': (context) => const PlayVideoFromNetwork(),
        '/fromNetworkQualityUrls': (context) =>
            const PlayVideoFromNetworkQualityUrls(),
        '/customVideo': (context) => const CustomVideoControlls(),
      },
      home: const MainPage(),
    );
  }
}

class MainPage extends StatefulWidget {
  const MainPage({Key? key}) : super(key: key);

  @override
  State<MainPage> createState() => _MainPageState();
}

class _MainPageState extends State<MainPage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: ListView(
          shrinkWrap: true,
          children: [
            // _button('Play video from File'),
            _button(
              'Play video from Network',
              onPressed: () => Navigator.of(context).pushNamed('/fromNetwork'),
            ),
            _button(
              'Play video from Youtube',
              onPressed: () => Navigator.of(context).pushNamed('/fromYoutube'),
            ),
            _button(
              'Play video from Network quality urls',
              onPressed: () =>
                  Navigator.of(context).pushNamed('/fromNetworkQualityUrls'),
            ),
            _button(
              'Play video from Asset',
              onPressed: () => Navigator.of(context).pushNamed('/fromAsset'),
            ),
            _button(
              'Play video from Vimeo',
              onPressed: () => Navigator.of(context).pushNamed('/fromVimeoId'),
            ),
            _button(
              'Custom Video player',
              onPressed: () => Navigator.of(context).pushNamed('/customVideo'),
            ),
          ],
        ),
      ),
    );
  }

  Widget _button(String text, {void Function()? onPressed}) {
    return Center(
      child: Padding(
        padding: const EdgeInsets.all(20),
        child: OutlinedButton(
          onPressed: onPressed ?? () {},
          child: Text(
            text,
            style: const TextStyle(fontSize: 16, fontWeight: FontWeight.bold),
          ),
        ),
      ),
    );
  }
}

Please run the app in the example/ folder to start playing!

Author: NewtaDev
Source Code: https://github.com/newtaDev/pod_player 
License: MIT license

#flutter #dart #players 

Pod_player: Video Player for Flutter Web & Mobile Devices, Play Video

TBIB Cached Video Player with Flutter

TBIB Cached Video Player

A flutter plugin that has been forked from the official video_player package except that it supports caching in Android and iOS. Web plugin will work like official video_player i.e. without caching support.

Installation

First, add tbib cached_video_player as a dependency in your pubspec.yaml file.

Follow the Android and iOS configuration steps of the official video_player package. This plugin won't work in Desktop.

Issues

  • maxFileSize and maxCacheSize are hardcoded at 100MiB and 1GiB respectively in Android. 

Use this package as a library

Depend on it

Run this command:

With Dart:

 $ dart pub add tbib_cached_video_player

With Flutter:

 $ flutter pub add tbib_cached_video_player

This will add a line like this to your package's pubspec.yaml (and run an implicit dart pub get):

dependencies:
  tbib_cached_video_player: ^0.0.1

Alternatively, your editor might support dart pub get or flutter pub get. Check the docs for your editor to learn more.

Import it

Now in your Dart code, you can use:

import 'package:tbib_cached_video_player/tbib_cached_video_player.dart'; 

example/lib/main.dart

// ignore_for_file: public_member_api_docs

/// An example of using the plugin, controlling lifecycle and playback of the
/// video.

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:tbib_cached_video_player/tbib_cached_video_player.dart';

void main() {
  runApp(
    MaterialApp(
      home: _App(),
    ),
  );
}

class _App extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return DefaultTabController(
      length: 3,
      child: Scaffold(
        key: const ValueKey<String>('home_page'),
        appBar: AppBar(
          title: const Text('Video player example'),
          actions: <Widget>[
            IconButton(
              key: const ValueKey<String>('push_tab'),
              icon: const Icon(Icons.navigation),
              onPressed: () {
                Navigator.push<_PlayerVideoAndPopPage>(
                  context,
                  MaterialPageRoute<_PlayerVideoAndPopPage>(
                    builder: (BuildContext context) => _PlayerVideoAndPopPage(),
                  ),
                );
              },
            )
          ],
          bottom: const TabBar(
            isScrollable: true,
            tabs: <Widget>[
              Tab(
                icon: Icon(Icons.cloud),
                text: "Remote",
              ),
              Tab(icon: Icon(Icons.insert_drive_file), text: "Asset"),
              Tab(icon: Icon(Icons.list), text: "List example"),
            ],
          ),
        ),
        body: TabBarView(
          children: <Widget>[
            _BumbleBeeRemoteVideo(),
            _ButterFlyAssetVideo(),
            _ButterFlyAssetVideoInList(),
          ],
        ),
      ),
    );
  }
}

class _ButterFlyAssetVideoInList extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return ListView(
      children: <Widget>[
        const _ExampleCard(title: "Item a"),
        const _ExampleCard(title: "Item b"),
        const _ExampleCard(title: "Item c"),
        const _ExampleCard(title: "Item d"),
        const _ExampleCard(title: "Item e"),
        const _ExampleCard(title: "Item f"),
        const _ExampleCard(title: "Item g"),
        Card(
            child: Column(children: <Widget>[
          Column(
            children: <Widget>[
              const ListTile(
                leading: Icon(Icons.cake),
                title: Text("Video video"),
              ),
              Stack(
                  alignment: FractionalOffset.bottomRight +
                      const FractionalOffset(-0.1, -0.1),
                  children: <Widget>[
                    _ButterFlyAssetVideo(),
                    Image.asset('assets/flutter-mark-square-64.png'),
                  ]),
            ],
          ),
        ])),
        const _ExampleCard(title: "Item h"),
        const _ExampleCard(title: "Item i"),
        const _ExampleCard(title: "Item j"),
        const _ExampleCard(title: "Item k"),
        const _ExampleCard(title: "Item l"),
      ],
    );
  }
}

/// A filler card to show the video in a list of scrolling contents.
class _ExampleCard extends StatelessWidget {
  const _ExampleCard({Key? key, required this.title}) : super(key: key);

  final String title;

  @override
  Widget build(BuildContext context) {
    return Card(
      child: Column(
        mainAxisSize: MainAxisSize.min,
        children: <Widget>[
          ListTile(
            leading: const Icon(Icons.airline_seat_flat_angled),
            title: Text(title),
          ),
          ButtonBar(
            children: <Widget>[
              TextButton(
                child: const Text('BUY TICKETS'),
                onPressed: () {
                  /* ... */
                },
              ),
              TextButton(
                child: const Text('SELL TICKETS'),
                onPressed: () {
                  /* ... */
                },
              ),
            ],
          ),
        ],
      ),
    );
  }
}

class _ButterFlyAssetVideo extends StatefulWidget {
  @override
  _ButterFlyAssetVideoState createState() => _ButterFlyAssetVideoState();
}

class _ButterFlyAssetVideoState extends State<_ButterFlyAssetVideo> {
  late VideoPlayerController _controller;

  @override
  void initState() {
    super.initState();
    _controller = VideoPlayerController.asset('assets/Butterfly-209.mp4');

    _controller.addListener(() {
      setState(() {});
    });
    _controller.setLooping(true);
    _controller.initialize().then((_) => setState(() {}));
    _controller.play();
  }

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return SingleChildScrollView(
      child: Column(
        children: <Widget>[
          Container(
            padding: const EdgeInsets.only(top: 20.0),
          ),
          const Text('With assets mp4'),
          Container(
            padding: const EdgeInsets.all(20),
            child: AspectRatio(
              aspectRatio: _controller.value.aspectRatio,
              child: Stack(
                alignment: Alignment.bottomCenter,
                children: <Widget>[
                  VideoPlayer(_controller),
                  _ControlsOverlay(controller: _controller),
                  VideoProgressIndicator(_controller, allowScrubbing: true),
                ],
              ),
            ),
          ),
        ],
      ),
    );
  }
}

class _BumbleBeeRemoteVideo extends StatefulWidget {
  @override
  _BumbleBeeRemoteVideoState createState() => _BumbleBeeRemoteVideoState();
}

class _BumbleBeeRemoteVideoState extends State<_BumbleBeeRemoteVideo> {
  late VideoPlayerController _controller;

  Future<ClosedCaptionFile> _loadCaptions() async {
    final String fileContents = await DefaultAssetBundle.of(context)
        .loadString('assets/bumble_bee_captions.vtt');
    return WebVTTCaptionFile(
        fileContents); // For vtt files, use WebVTTCaptionFile
  }

  @override
  void initState() {
    super.initState();
    _controller = VideoPlayerController.network(
      'https://flutter.github.io/assets-for-api-docs/assets/videos/bee.mp4',
      closedCaptionFile: _loadCaptions(),
      videoPlayerOptions: VideoPlayerOptions(mixWithOthers: true),
    );

    _controller.addListener(() {
      setState(() {});
    });
    _controller.setLooping(true);
    _controller.initialize();
  }

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return SingleChildScrollView(
      child: Column(
        children: <Widget>[
          Container(padding: const EdgeInsets.only(top: 20.0)),
          const Text('With remote mp4'),
          Container(
            padding: const EdgeInsets.all(20),
            child: AspectRatio(
              aspectRatio: _controller.value.aspectRatio,
              child: Stack(
                alignment: Alignment.bottomCenter,
                children: <Widget>[
                  VideoPlayer(_controller),
                  ClosedCaption(text: _controller.value.caption.text),
                  _ControlsOverlay(controller: _controller),
                  VideoProgressIndicator(_controller, allowScrubbing: true),
                ],
              ),
            ),
          ),
        ],
      ),
    );
  }
}

class _ControlsOverlay extends StatelessWidget {
  const _ControlsOverlay({Key? key, required this.controller})
      : super(key: key);

  static const _examplePlaybackRates = [
    0.25,
    0.5,
    1.0,
    1.5,
    2.0,
    3.0,
    5.0,
    10.0,
  ];

  final VideoPlayerController controller;

  @override
  Widget build(BuildContext context) {
    return Stack(
      children: <Widget>[
        AnimatedSwitcher(
          duration: const Duration(milliseconds: 50),
          reverseDuration: const Duration(milliseconds: 200),
          child: controller.value.isPlaying
              ? const SizedBox.shrink()
              : Container(
                  color: Colors.black26,
                  child: const Center(
                    child: Icon(
                      Icons.play_arrow,
                      color: Colors.white,
                      size: 100.0,
                    ),
                  ),
                ),
        ),
        GestureDetector(
          onTap: () {
            controller.value.isPlaying ? controller.pause() : controller.play();
          },
        ),
        Align(
          alignment: Alignment.topRight,
          child: PopupMenuButton<double>(
            initialValue: controller.value.playbackSpeed,
            tooltip: 'Playback speed',
            onSelected: (speed) {
              controller.setPlaybackSpeed(speed);
            },
            itemBuilder: (context) {
              return [
                for (final speed in _examplePlaybackRates)
                  PopupMenuItem(
                    value: speed,
                    child: Text('${speed}x'),
                  )
              ];
            },
            child: Padding(
              padding: const EdgeInsets.symmetric(
                // Using less vertical padding as the text is also longer
                // horizontally, so it feels like it would need more spacing
                // horizontally (matching the aspect ratio of the video).
                vertical: 12,
                horizontal: 16,
              ),
              child: Text('${controller.value.playbackSpeed}x'),
            ),
          ),
        ),
      ],
    );
  }
}

class _PlayerVideoAndPopPage extends StatefulWidget {
  @override
  _PlayerVideoAndPopPageState createState() => _PlayerVideoAndPopPageState();
}

class _PlayerVideoAndPopPageState extends State<_PlayerVideoAndPopPage> {
  late VideoPlayerController _videoPlayerController;
  bool startedPlaying = false;

  @override
  void initState() {
    super.initState();

    _videoPlayerController =
        VideoPlayerController.asset('assets/Butterfly-209.mp4');
    _videoPlayerController.addListener(() {
      if (startedPlaying && !_videoPlayerController.value.isPlaying) {
        Navigator.pop(context);
      }
    });
  }

  @override
  void dispose() {
    _videoPlayerController.dispose();
    super.dispose();
  }

  Future<bool> started() async {
    await _videoPlayerController.initialize();
    await _videoPlayerController.play();
    startedPlaying = true;
    return true;
  }

  @override
  Widget build(BuildContext context) {
    return Material(
      elevation: 0,
      child: Center(
        child: FutureBuilder<bool>(
          future: started(),
          builder: (BuildContext context, AsyncSnapshot<bool> snapshot) {
            if (snapshot.data == true) {
              return AspectRatio(
                aspectRatio: _videoPlayerController.value.aspectRatio,
                child: VideoPlayer(_videoPlayerController),
              );
            } else {
              return const Text('waiting for video to load');
            }
          },
        ),
      ),
    );
  }
} 

Download Details:

Author: the-best-is-best

Source Code: https://github.com/the-best-is-best/tbib_cahched_video_player

#flutter #video #players 

TBIB Cached Video Player with Flutter
Reid  Rohan

Reid Rohan

1644463980

Clappr: An Extensible Media Player for The Web

Huge changes in the latest version. See 0.4.0 version changelog for more information

    Clappr is an extensible media player for the web. Your architecture is projected primarily into plugins, adding low accoupling by design to the project and the possibility to add infinitely features easily.

Clappr uses by default the HTMLVideoElement which guarantees support to many platforms. You have the possibility to extends the default HTML5 playback or the playback interface to create one new media support just like a plugin!

Clappr is a composition of two other projects: @clappr/core and @clappr/plugins.

The @clappr/core contains the basic functionalities from Clappr (plugin architecture, class abstractions, public interfaces, events handlers and etc) and the @clappr/plugins are the repository where the plugins maintained by the Clappr team lives. More info about those projects into your repositories.

All Clappr projects are written in *.js using the latest features of ECMAScript.

Clappr is under development but production-ready. Feel free to open issues and send pull requests.

🚩 Table of Contents

🎬 Usage

Via script tag:

Add the following script on your HTML:

<head>
  <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/@clappr/player@latest/dist/clappr.min.js"></script>
</head>

Now, create the player:

<body>
  <div id="player"></div>
  <script>
    var player = new Clappr.Player({source: "http://your.video/here.mp4", parentId: "#player"});
  </script>
</body>

📹 Demo

Live demo to test, with a possibility to add external plugins.

📚 API Documentation

You can check the current API doc via @clappr/core here.

🛠️ Configuration

You can check the embed parameters supported by @clappr/core here.

🔌 Built-in Plugins

You can check the plugins used on Clappr player via @clappr/plugins here.

🤝 Third party plugins/integrations

External Plugins

PluginStatusCompatible with latest ClapprURL
Media ControlReadyYeshttps://github.com/joaopaulovieira/clappr-media-control-plugin
Video Queue (Playlist)ReadyYeshttps://github.com/joaopaulovieira/clappr-queue-plugin
Thumbnails on seekbarReadyYeshttps://github.com/tjenkinson/clappr-thumbnails-plugin
MarkersReadyYeshttps://github.com/tjenkinson/clappr-markers-plugin
Level SelectorReadyYeshttps://github.com/clappr/clappr-level-selector-plugin
360 videosReadyYeshttps://github.com/thiagopnts/video-360
ChromecastReadyYeshttps://github.com/clappr/clappr-chromecast-plugin
DASH with shakaReadyYeshttps://github.com/clappr/dash-shaka-playback
Playback SpeedReadyYeshttps://github.com/bikegriffith/clappr-playback-rate-plugin
Clappr StatsReadyYeshttps://github.com/leandromoreira/clappr-stats
Clappr Nerd StatsReadyYeshttps://github.com/lucasrodcosta/clappr-nerd-stats
Pause while farReadyYeshttps://github.com/leandromoreira/clappr-pause-tab-visibility
RTMPReadyYeshttps://github.com/clappr/clappr-rtmp-plugin
Picture-in-PictureReadyYeshttps://github.com/tjenkinson/clappr-pip-plugin
Hybrid P2P & CDNReadyYeshttps://support.streamroot.io/hc/en-us/articles/360000913654-Clappr
Comments on seekbarReady?https://github.com/Metrakit/clappr-comment-plugin
Voice controlReady?https://github.com/flavioribeiro/clappr-speech-control-plugin
DashWIPNohttps://github.com/shankardevy/clappr-dash-plugin
YoutubeReadyNohttps://github.com/towerz/clappr-youtube-playback
Googel IMA Pre RollReadyYeshttps://github.com/kslimani/clappr-google-ima-html5-preroll
VAST Ad pluginWIPNohttps://github.com/vix-simplex/clappr-ad-plugin
Dynamic OverlayReadyYeshttps://github.com/Lethea/clappr-dynamic-text-overlay
Scroll Text OverlayReadyYeshttps://github.com/Lethea/clappr-marquee-overlay
Playback Speed ControllerReadyYeshttps://github.com/Lethea/clapper-playback-speed-plugin-extended
FLVReadyYeshttps://github.com/andrefilimono/clappr-flvjs-playback
Context MenuReadyYeshttps://github.com/joaopaulovieira/clappr-context-menu-plugin

External Integrations

IntegrationStatusCompatible with latest ClapprURL
P2P Media LoaderReadyYeshttps://github.com/Novage/p2p-media-loader

🎞️ Supported Formats

FormatHLSMP4MP3WEBMDASHRTMPJPG/PNG/GIFFLV
IE10rtmp
IE11rtmprtmprtmp
Microsoft Edge??rtmprtmp?rtmp
Firefoxrtmprtmprtmprtmp
Chromertmprtmprtmp
Safarirtmprtmprtmprtmp
iPhone
iPad
Androidrtmprtmprtmp
WiiU Browser?rtmprtmp?
PS4 Browser?rtmprtmp?

rtmp means that the support is made by an external plugin.

⏯️ About Autoplay

Clappr has no control over autoplay Browser Policy.

Therefore, we're not able to execute play and unmute actions sequentially in every situation. There are a series of scenarios where the Browser blocks these actions based on it’s own policy.

Each browser has their own different restrictions, and the usual behavior is to activate the sound only after an user interaction with the player.

For more infos about auto play video policy, you can read these docs:

⁉️ FAQ & Troubleshooting

How to write a plugin?

See the wiki for more info.

How can I disable or override a plugin?

Let's say you want to disable or override a plugin.

Disable a plugin

// let's disable the loading animation (the 'spinner' plugin)
var player = new Clappr.Player({ ... });
// after attach
player.getPlugin('spinner').disable();

Override a plugin

// let's disable the loading animation (the 'spinner' plugin)
export default class NoSpinner extends UIContainerPlugin {
  get name() { return 'spinner' }
}
new Clappr.Player({ plugins: [NoSpinner]})

How can I use clappr with ReactJS?

https://medium.com/@bikegriffith/using-clappr-with-reactjs-14a338e3451f#.9a36w0dpj

How can I use clappr with ionic/angular?

https://github.com/clappr/clappr/issues/933#issuecomment-228540381

How can I Log messages with Clappr?

Add this snippet before you instantiate the player Clappr.Log.setLevel(0)

Common steps to verify issues

Very often people open issues related to stream not working, freezing, glitching, stopping, and so on. You can try the steps below, taking notes about the results:

  • try to run the same example at CDN
  • check the cors headers at your servers
  • try to run it on hls.js demo page
  • try to run it on flashls. demo page
  • try to run on your page the following source: http://www.streambox.fr/playlists/x36xhzz/x36xhzz.m3u8
  • try different browsers/OS's to see if the problems remain
  • try to use a tool to check the health of your stream (both input, ie: RTMP, and segmentation, ie: DASH or HLS): like mediainfo (for instance you could: mediainfo http://www.example.com/my.m3u8, Apple's mediastreamvalidator too, hls-analyzer and etc.
//HLS-Analyzer usage example

pip install m3u8
git clone https://github.com/epiclabs-io/hls-analyzer.git
cd hls-analyzer
python hls-analyzer.py http://www.streambox.fr/playlists/x36xhzz/x36xhzz.m3u8

How to handle player fatal errors?

Player fatal errors can be handled using onError API event.

var player = new Clappr.Player({
  parent: '#myplayer',
  source: 'http://path.to/my/video.mp4',
  events: {
    onError: function(e) {
      // Here the code to handle the error
    }
  }
});

Note: the type of error event object depends on the type of the playback component resolved to play the video.

Example

This is a simple example using the no_op playback to display error messages.

You can try the following Javascript code on Clappr demo page:

var playerElement = document.getElementById("player-wrapper");

var r = 3; // Retry attempts

var player = new Clappr.Player({
  // source: 'http://clappr.io/highline.mp4',
  source: 'http://clappr.io/bad_highline.mp4',
  disableErrorScreen: true, // Disable the internal error screen plugin
  height: 360,
  width: 640,
  events: {
    onError: function(e) {
      r--;
      var s = player.options.source;
      // Replace previous line by the following line to simulate successful recovery
      // var s = (r > 2) ? player.options.source : 'http://clappr.io/highline.mp4';
      var t = 10;
      var retry = function() {
        if (t === 0) {
          var o = player.options;
          o.source = s;
          player.configure(o);
          return;
        }
        Clappr.$('#retryCounter').text(t);
        t--;
        setTimeout(retry, 1000);
      };
      player.configure({
        autoPlay: true,
        source: 'playback.error',
        playbackNotSupportedMessage: 'Network fatal error.' + ((r > 0)
            ? ' Retrying in <span id="retryCounter"></span> seconds ...'
            : ' All retry attempts failed'),
      });
      if (r > 0) {
        retry();
      }
    }
  }
});

player.attachTo(playerElement);

Another example

This example use a custom error container plugin to display error messages.

You can try the following Javascript code on Clappr demo page:

var playerElement = document.getElementById("player-wrapper");

var ErrorPlugin = Clappr.ContainerPlugin.extend({
  name: 'error_plugin',
  background: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAoAAAAFoBAMAAAA1HFdiAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAG1BMVEX5+fn//wAA//8A/wD/AP//AAAAAP8XFxf///8H5gWfAAAAAWJLR0QIht6VegAAAAd0SU1FB98IBRIsAXmGk48AAAI5SURBVHja7dJBDYBADADBs4AFLGABC1iohbOPhv1BMvu+NLlp10odqTN1pe7Uk5pQ8wMIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECDA/wKWxzM71T7ZZrfltNnppgACBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAL8B+ALjSfYzPnmdzgAAACV0RVh0ZGF0ZTpjcmVhdGUAMjAxNS0wOC0wNVQxODo0NDowMSswMTowMCL95a4AAAAldEVYdGRhdGU6bW9kaWZ5ADIwMTUtMDgtMDVUMTg6NDQ6MDErMDE6MDBToF0SAAAAAElFTkSuQmCC',
  bindEvents: function() { this.listenTo(this.container, Clappr.Events.CONTAINER_ERROR, this.onError) },
  hide: function() { this._err && this._err.remove() },
  show: function() {
    var $ = Clappr.$
    this.hide();
    var txt = (this.options.errorPlugin && this.options.errorPlugin.text) ? this.options.errorPlugin.text : 'A fatal error occured.';
    this._err = $('<div>')
      .css({
        'position': 'absolute',
        'z-index': '999',
        'width': '100%',
        'height': '100%',
        'background-image': 'url(' + this.background + ')',
        'background-size': 'contain',
        'background-repeat': 'no-repeat',
        'padding-top': '15%',
        'text-align': 'center',
        'font-weight': 'bold',
        'text-shadow': '1px 1px #fff',
      })
      .append($('<h2>')
        .text(txt)
        .css({
          'font-size': '200%',
        }))
      .append($('<p>').html('Retrying in <span class="retry-counter">10</span> seconds ...')
        .css({
          'font-size': '120%',
          'margin': '15px',
        }));
    this.container && this.container.$el.prepend(this._err);
  },
  onError: function(e) {
    if (!this.container) return;
    this.show();
    this.container.getPlugin('click_to_pause').disable();
    var tid, t = 10, retry = function() {
      clearTimeout(tid);
      if (t === 0) {
        this.container.getPlugin('click_to_pause').enable();
        if (this.options.errorPlugin && this.options.errorPlugin.onRetry) {
          this.options.errorPlugin.onRetry(e);
          return;
        } else {
          this.container.stop();
          this.container.play();
          return;
        }
      }
      $('.retry-counter').text(t);
      t--;
      tid = setTimeout(retry, 1000);
    }.bind(this);
    retry();
  }
});

var player = new Clappr.Player({
  disableErrorScreen: true, // Disable the internal error screen plugin
  source: 'http://clappr.io/bad_highline.mp4',
  plugins: [ErrorPlugin],
  errorPlugin: {
    // text: 'My custom error message.',
    onRetry: function(e) {
      // simulate successful recovery
      // or decide here what to do between each retry
      player.configure({
        source: 'http://clappr.io/highline.mp4',
        autoPlay: true,
      });
    }
  },
  height: 360,
  width: 640
});

player.attachTo(playerElement);

🚀 Companies using Clappr

https://github.com/clappr/clappr/issues/522

🙌 Contributors

This project exists thanks to all the people who contribute.

🌟 Sponsor

image

Author: Clappr
Source Code: https://github.com/clappr/clappr 
License: BSD-3-Clause License

#javascript #players #video 

Clappr: An Extensible Media Player for The Web
Reid  Rohan

Reid Rohan

1644441300

Video.js: Open Source HTML5 & Flash Video Player

Video.js - HTML5 Video Player

Video.js is a web video player built from the ground up for an HTML5 world. It supports HTML5 and Flash video, as well as YouTube and Vimeo (through plugins). It supports video playback on desktops and mobile devices. This project was started mid 2010, and the player is now used on over 50,000 100,000 200,000 400,000 websites.

Table of Contents

Quick Start

Thanks to the awesome folks over at Fastly, there's a free, CDN hosted version of Video.js that anyone can use. Add these tags to your document's <head>:

<link href="//vjs.zencdn.net/7.8.2/video-js.min.css" rel="stylesheet">
<script src="//vjs.zencdn.net/7.8.2/video.min.js"></script>

For the latest version of video.js and URLs to use, check out the Getting Started page on our website.

Video.js version 7 (and newer) CDN builds do not send any data to Google Analytics.

In older versions of Video.js (6 and earlier), in the vjs.zencdn.net CDN-hosted versions we include a stripped down Google Analytics pixel that tracks a random sampling (currently 1%) of players loaded from the CDN. This allows us to see (roughly) what browsers are in use in the wild, along with other useful metrics such as OS and device. If you'd like to disable analytics, you can simply include the following global before including Video.js via the free CDN:

<script>window.HELP_IMPROVE_VIDEOJS = false;</script>

Alternatively, you can include Video.js by getting it from npm, downloading from GitHub releases or by including it via unpkg or another JavaScript CDN like CDNjs. These releases do not include Google Analytics tracking at all.

<!-- unpkg : use the latest version of Video.js -->
<link href="https://unpkg.com/video.js/dist/video-js.min.css" rel="stylesheet">
<script src="https://unpkg.com/video.js/dist/video.min.js"></script>

<!-- unpkg : use a specific version of Video.js (change the version numbers as necessary) -->
<link href="https://unpkg.com/video.js@7.8.2/dist/video-js.min.css" rel="stylesheet">
<script src="https://unpkg.com/video.js@7.8.2/dist/video.min.js"></script>

<!-- cdnjs : use a specific version of Video.js (change the version numbers as necessary) -->
<link href="https://cdnjs.cloudflare.com/ajax/libs/video.js/7.8.1/video-js.min.css" rel="stylesheet">
<script src="https://cdnjs.cloudflare.com/ajax/libs/video.js/7.8.1/video.min.js"></script>

Next, using Video.js is as simple as creating a <video> element, but with an additional data-setup attribute. At a minimum, this attribute must have a value of '{}', but it can include any Video.js options - just make sure it contains valid JSON!

<video
    id="my-player"
    class="video-js"
    controls
    preload="auto"
    poster="//vjs.zencdn.net/v/oceans.png"
    data-setup='{}'>
  <source src="//vjs.zencdn.net/v/oceans.mp4" type="video/mp4"></source>
  <source src="//vjs.zencdn.net/v/oceans.webm" type="video/webm"></source>
  <source src="//vjs.zencdn.net/v/oceans.ogv" type="video/ogg"></source>
  <p class="vjs-no-js">
    To view this video please enable JavaScript, and consider upgrading to a
    web browser that
    <a href="https://videojs.com/html5-video-support/" target="_blank">
      supports HTML5 video
    </a>
  </p>
</video>

When the page loads, Video.js will find this element and automatically setup a player in its place.

If you don't want to use automatic setup, you can leave off the data-setup attribute and initialize a <video> element manually using the videojs function:

var player = videojs('my-player');

The videojs function also accepts an options object and a callback to be invoked when the player is ready:

var options = {};

var player = videojs('my-player', options, function onPlayerReady() {
  videojs.log('Your player is ready!');

  // In this context, `this` is the player that was created by Video.js.
  this.play();

  // How about an event listener?
  this.on('ended', function() {
    videojs.log('Awww...over so soon?!');
  });
});

If you're ready to dive in, the Getting Started page and documentation are the best places to go for more information. If you get stuck, head over to our Slack channel!

Contributing

Video.js is a free and open source library, and we appreciate any help you're willing to give - whether it's fixing bugs, improving documentation, or suggesting new features. Check out the contributing guide for more!

Video.js uses BrowserStack for compatibility testing.

Code of Conduct

Please note that this project is released with a Contributor Code of Conduct. By participating in this project you agree to abide by its terms.

Author: Videojs
Source Code: https://github.com/videojs/video.js 
License: View license

#javascript #html #players 

Video.js: Open Source HTML5 & Flash Video Player

Flutter Tencent Live Player

Based on TXLiteAVSDK_Player Tencent player package flutter sdk currently supports live broadcast, sdk only provides core functions, specific functions need to be customized, there is a set of attached ui in the example.

Left iOS Right Android

pub address https://pub.dev/packages/ftl_player

Image text

Image text

Simple to use


 @override
  void initState() {
    super.initState();
    FTLPlayer.init().then((value){
      this.livePlayerController = value;
      this.setState(() {});
    });
  }

Container(height: 200, child: FTLPlayerWidget(this.livePlayerController)),

Detailed use https://github.com/tion126/flutter_live

You can customize and modify the UI, and you can also play live broadcasts on other platforms without Tencent.

Currently known issues

1. Android needs to set the hls format to play normally

Use this package as a library

Depend on it

Run this command:

With Flutter:

 $ flutter pub add ftl_player

This will add a line like this to your package's pubspec.yaml (and run an implicit flutter pub get):

dependencies:
  ftl_player: ^2.0.0

Alternatively, your editor might support or flutter pub get. Check the docs for your editor to learn more.

Import it

Now in your Dart code, you can use:

import 'package:ftl_player/ftl_player.dart';

example/lib/main.dart

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:ftl_player/ftl_player.dart';

void main() => runApp(app());

Widget app() {
  SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle(
    statusBarColor: Colors.transparent,
    systemNavigationBarColor: Colors.white,
    statusBarIconBrightness: Brightness.dark,
  ));

  return MaterialApp(initialRoute: "/", routes: {
    "/": (context) => HomePage(),
    "/page1": (context) => PlayerExample(),
  });
}

class HomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: CupertinoButton(
          child: Text("Player"),
          onPressed: () {
            Navigator.of(context).pushNamed("/page1");
          },
        ),
      ),
    );
  }
}

class PlayerExample extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    return PlayerExampleState();
  }
}

class PlayerExampleState extends State<PlayerExample>{
   FTLPlayerController? livePlayerController;

  @override
  void initState() {
    super.initState();
    FTLPlayer.init().then((value){
      this.livePlayerController = value;
      this.setState(() {});
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        backgroundColor: Colors.white,
        body: SingleChildScrollView(
            child: Column(children: [
          Padding(padding: EdgeInsets.only(top: 50)),
          Container(height: 200, child: FTLPlayerWidget(this.livePlayerController)),
          Padding(padding: EdgeInsets.only(top: 30)),
          _optBtn()
        ])),
      );
  }

  Widget _optBtn() {
    return Padding(
      padding: const EdgeInsets.only(left: 45.0, right: 45.0, top: 0.0, bottom: 50.0),
      child: Wrap(
        children: <Widget>[
          CupertinoButton(
            onPressed: () {
              this.livePlayerController!.start("http://1011.hlsplay.aodianyun.com/demo/game.flv");
            },
            child: new Text("Start"),
          ),
          CupertinoButton(
            onPressed: () {
              this.livePlayerController!.pause();
            },
            child: Text("pause"),
          ),
          CupertinoButton(
            onPressed: () {
              this.livePlayerController!.resume();
            },
            child: new Text("resume"),
          ),
          CupertinoButton(
            onPressed: () {
              this.livePlayerController!.dispose();
            },
            child: new Text("dispose"),
          ),
          CupertinoButton(
            onPressed: () {
              this.livePlayerController!.pause();
              Navigator.of(context).pushNamed("/page1").then((value){
                this.livePlayerController!.resume();
              });
            },
            child: new Text("new page"),
          )
        ],
      ),
    );
  }


}

Download Details:

Author: tion126

Source Code: https://github.com/tion126/ftl_player

#flutter  #players 

Flutter Tencent Live Player

A Ogg Opus File Player for Flutter

ogg_opus_player

a ogg opus file player for flutter.

platform required os version
iOS10.0
macOS10.12

Getting Started

  1. add ogg_opus_player to your pubspec.yaml
  ogg_opus_player: $latest_version
  1. then you can play you opus ogg file from OggOpusPlayer

final player = OggOpusPlayer("file_path");

player.play();
player.pause();

player.dipose();

LICENSE

see LICENSE file

Use this package as a library

Depend on it

Run this command:

With Flutter:

 $ flutter pub add ogg_opus_player

This will add a line like this to your package's pubspec.yaml (and run an implicit flutter pub get):

dependencies:
  ogg_opus_player: ^0.1.0

Alternatively, your editor might support or flutter pub get. Check the docs for your editor to learn more.

Import it

Now in your Dart code, you can use:

import 'package:ogg_opus_player/ogg_opus_player.dart';

example/lib/main.dart

import 'dart:async';
import 'dart:io';

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:ogg_opus_player/ogg_opus_player.dart';
import 'package:path/path.dart' as p;
import 'package:path_provider/path_provider.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatefulWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  bool _copyCompleted = false;

  String _path = '';

  @override
  void initState() {
    super.initState();
    _copyAssets();
  }

  Future<void> _copyAssets() async {
    final dir = await getApplicationDocumentsDirectory();
    final dest = File(p.join(dir.path, "test.ogg"));
    _path = dest.path;
    if (await dest.exists()) {
      setState(() {
        _copyCompleted = true;
      });
      return;
    }

    final bytes = await rootBundle.load('audios/test.ogg');
    await dest.writeAsBytes(bytes.buffer.asUint8List());
    setState(() {
      _copyCompleted = true;
    });
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: const Text('Plugin example app'),
        ),
        body: _copyCompleted
            ? PlayerBody(path: _path)
            : const Center(
                child: SizedBox(
                  width: 24,
                  height: 24,
                  child: CircularProgressIndicator(),
                ),
              ),
      ),
    );
  }
}

class PlayerBody extends StatefulWidget {
  const PlayerBody({Key? key, required this.path}) : super(key: key);

  final String path;

  @override
  State<PlayerBody> createState() => _PlayerBodyState();
}

class _PlayerBodyState extends State<PlayerBody> {
  late OggOpusPlayer _player;

  Timer? timer;

  double _playingPosition = 0;

  @override
  void initState() {
    super.initState();
    _player = OggOpusPlayer(widget.path);
    timer = Timer.periodic(const Duration(milliseconds: 50), (timer) {
      setState(() {
        _playingPosition = _player.currentPosition;
      });
    });
  }

  @override
  void dispose() {
    timer?.cancel();
    _player.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Center(
      child: Column(
        mainAxisSize: MainAxisSize.min,
        children: [
          Text('position: ${_playingPosition.toStringAsFixed(2)}'),
          const SizedBox(height: 8),
          IconButton(
            onPressed: () {
              setState(() {
                _player.dispose();
                _player = OggOpusPlayer(widget.path);
              });
            },
            icon: const Icon(Icons.refresh),
          ),
          const SizedBox(height: 8),
          ValueListenableBuilder(
            valueListenable: _player.state,
            builder: (context, state, child) {
              if (state == PlayerState.playing) {
                return IconButton(
                  onPressed: () {
                    _player.pause();
                  },
                  icon: const Icon(Icons.pause),
                );
              } else {
                return IconButton(
                  onPressed: () {
                    if (state == PlayerState.ended) {
                      _player.dispose();
                      _player = OggOpusPlayer(widget.path);
                      _player.play();
                    } else {
                      _player.play();
                    }
                  },
                  icon: const Icon(Icons.play_arrow),
                );
              }
            },
          ),
        ],
      ),
    );
  }
} 

Download Details:

Author: flutter-plugins

Source Code: https://github.com/MixinNetwork/flutter-plugins/tree/main/packages/ogg_opus_player

#flutter #players 

A Ogg Opus File Player for Flutter
Ragib aburuken

Ragib aburuken

1631622772

Introducing New Multiplayer Tournament Feature: Chapayev 2

Chapayev 2: Best Checkers 3D board Game is a multiplayer online & offline board game that boosts the inner adrenaline rush.

In this thrilling, fast-paced, and competitive strategy game, you will fight for survival against your friend from all over the world to win tournaments and become a legend among your peers. You will have to use your wit, tactics, and cunning to formulate just the right strategy to outsmart your opponent in every battle.

It tests your intelligence, your strategy, and your knowledge. It will always be online multiplayer with great graphics and realistic physics – the game is designed to make you feel like you are fighting for your army.

The game is packed with new features never seen before in any other game of this genre. A brand new type of graphics engine renders even more stunning effects than any other checkers board game. Now the gameplay itself is even more exciting than ever before, with an increased number of players at the same time.

The game has recently launched the latest feature of Multiplayer Tourney. To know about the latest feature continue reading the article.

Win Multiplayer tourney and climb to the top of worldwide ranking tables or play for fun and win points!

Now let’s see how can you leverage the MultiPlayer Tourney update stepwise:

Step 1:

Step-1 - Chapayev 2

First, one player has to create a tournament using coins such as 500 coins, 1000 coins, etc.

Step 2:

Invite as many players as you want using your invite feature within the game.

For More Step CLICK HERE

 

#3dboardgame  #boardgame  #best3dboardgame  #mobileboardgame  #checkers  #checkersboardgame  #draughts  #draughtsgame  #checkers3dboardgame  #onlineboardgame  #mobilegame  #mobilegaming  #gaming  #gamer  #game  #bestmobilegame  #strategygame  #play  #players  #gamelovers  #mobilegamelovers  #proplayers  #challenge  #chapayev2  #multiplayergame 

Introducing New Multiplayer Tournament Feature: Chapayev 2
Erwin  Boyer

Erwin Boyer

1624684440

How AI Chatbot Data Is Helping Casinos Customise Their Players’ Needs

All businesses and people rely on the assistance of many varying technologies to improve efficiency in the workplace and home. Work and play processes, especially those relating to communication, are made easier through instant chats, VOIP and even video conferencing. Many industries relish the applicable nature offered by technology sciences and artificial technology not only captures the imagination but produces workable data.

The use of AI technology in the iGaming industry has almost become proverbial. However, there are differences in how this technology is received and used by players. Some players find instant problem-solving solutions offered by chatbots inviting, while others prefer the human touch.

Even gigantic iGaming groups are not immune to customer dissatisfaction. Handling the issues does not only rely on empathetic human approaches, but it also depends on acquiring necessary customer data.

#chatbots #latest news #how ai chatbot data is helping casinos customise their players’ needs #ai chatbot data #casinos #players

How AI Chatbot Data Is Helping Casinos Customise Their Players’ Needs

NFL, NBA Players Hacked in Would-Be Cyber-Slam-Dunk

NFL and NBA athletes whose social-media accounts were taken over have been thrown the ball of justice.

Multiple professional and semi-pro athletes were victimized by two men who infiltrated their personal accounts, according to testimony in federal court on Wednesday. Trevontae Washington of Thibodaux, La., and Ronnie Magrehbi, of Orlando, Fla., faced separate judges in the Eastern District of Louisiana and the Middle District of Florida, respectively, and were charged with one count of conspiracy to commit wire fraud, and one count of conspiracy to commit computer fraud and abuse.

Federal prosecutors alleged that between December 2017 and April 2019, Washington and Magrehbi actively took part in illegal schemes to gain access to social media and other personal online accounts of the players.

Washington allegedly specialized in NBA and NFL players, and phished for their credentials by taking advantage of public platforms like Instagram. He would send them messages with embedded links to what appeared to be legitimate social media log-in sites, prosecutors said, but these were actually phishing pages used to steal the athletes’ user names and passwords. Once the athletes entered their credentials, they would be sent to Washington, who, along with others allegedly locked the athletes out of their accounts. They also used the credentials against other accounts, banking on password reuse. Prosecutors claimed that Washington then sold access to the compromised accounts to others for amounts ranging from $500 to $1,000.

Magrehbi, meanwhile, is alleged to have obtained access to accounts belonging to one professional football player, including an Instagram account and personal email account. Magrehbi took a ransomware-like tack, prosecutors said, and extorted the player. He demanded payment in return for restoring access to the accounts – and was paid, according to Department of Justice documents. However, even though the player sent funds on at least one occasion, portions of which were transferred to a personal bank account controlled by Magrehbi – he was double-crossed and the athlete never regained access, prosecutors said.

The DoJ has not released the names of the affected players.

“Instagram is built as a mobile-first experience, which means that these attackers knew they could build a mobile-specific phishing campaign to increase the likelihood of success,” Hank Schless, senior manager of security solutions at Lookout, told Threatpost. “Since we carry our mobile devices with us all the time, we trust them to be inherently secure. Threat actors know this and socially engineer targets through SMS, social media and third-party messaging apps and convince them to click a malicious link.”

#government #hacks #web security #account takeover #charged #department of justice #extortion #federal court #federal crimes #hack #nba #nfl #players #ronnie magrehbi #social media accounts #trevontae washington

NFL, NBA Players Hacked in Would-Be Cyber-Slam-Dunk