NextLevelSessionExporter is an export and transcode media library for iOS written in Swift.

Overview

NextLevelSessionExporter 🔄

NextLevelSessionExporter is an export and transcode media library for iOS written in Swift.

Build Status Pod Version Swift Version GitHub license

The library provides customizable audio and video encoding options unlike AVAssetExportSession and without having to learn the intricacies of AVFoundation. It was a port of SDAVAssetExportSession with inspiration from SCAssetExportSession – which are great obj-c alternatives.

  • Looking for a capture library? Check out NextLevel.
  • Looking for a video player? Check out Player

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

Quick Start

0.4.5" # Carthage github "nextlevel/NextLevelSessionExporter" ~> 0.4.5 # Swift PM let package = Package( dependencies: [ .Package(url: "https://github.com/nextlevel/NextLevelSessionExporter", majorVersion: 0) ] ) ">
# CocoaPods

pod "NextLevelSessionExporter", "~> 0.4.5"

# Carthage

github "nextlevel/NextLevelSessionExporter" ~> 0.4.5

# Swift PM

let package = Package(
    dependencies: [
        .Package(url: "https://github.com/nextlevel/NextLevelSessionExporter", majorVersion: 0)
    ]
)

Alternatively, drop the source files into your Xcode project.

Example

Simply use the AVAsset extension or create and use an instance of NextLevelSessionExporter directly.

let tmpURL = URL(fileURLWithPath: NSTemporaryDirectory(), isDirectory: true)
    .appendingPathComponent(ProcessInfo().globallyUniqueString)
    .appendingPathExtension("mp4")
exporter.outputURL = tmpURL

let compressionDict: [String: Any] = [
    AVVideoAverageBitRateKey: NSNumber(integerLiteral: 6000000),
    AVVideoProfileLevelKey: AVVideoProfileLevelH264HighAutoLevel as String,
]
let videoOutputConfig = [
    AVVideoCodecKey: AVVideoCodec.h264,
    AVVideoWidthKey: NSNumber(integerLiteral: 1920),
    AVVideoHeightKey: NSNumber(integerLiteral: 1080),
    AVVideoScalingModeKey: AVVideoScalingModeResizeAspectFill,
    AVVideoCompressionPropertiesKey: compressionDict
]
let audioOutputConfig = [
    AVFormatIDKey: kAudioFormatMPEG4AAC,
    AVEncoderBitRateKey: NSNumber(integerLiteral: 128000),
    AVNumberOfChannelsKey: NSNumber(integerLiteral: 2),
    AVSampleRateKey: NSNumber(value: Float(44100))
]

let asset = AVAsset(url: Bundle.main.url(forResource: "TestVideo", withExtension: "mov")!)
asset.nextlevel_export(outputURL: tmpURL, videoOutputConfiguration: videoOutputConfig, audioOutputConfiguration: audioOutputConfig)

Alternatively, you can use NextLevelSessionExporter directly.

let exporter = NextLevelSessionExporter(withAsset: asset)
exporter.outputFileType = AVFileType.mp4
let tmpURL = URL(fileURLWithPath: NSTemporaryDirectory(), isDirectory: true)
    .appendingPathComponent(ProcessInfo().globallyUniqueString)
    .appendingPathExtension("mp4")
exporter.outputURL = tmpURL

let compressionDict: [String: Any] = [
    AVVideoAverageBitRateKey: NSNumber(integerLiteral: 6000000),
    AVVideoProfileLevelKey: AVVideoProfileLevelH264HighAutoLevel as String,
]
exporter.videoOutputConfiguration = [
    AVVideoCodecKey: AVVideoCodec.h264,
    AVVideoWidthKey: NSNumber(integerLiteral: 1920),
    AVVideoHeightKey: NSNumber(integerLiteral: 1080),
    AVVideoScalingModeKey: AVVideoScalingModeResizeAspectFill,
    AVVideoCompressionPropertiesKey: compressionDict
]
exporter.audioOutputConfiguration = [
    AVFormatIDKey: kAudioFormatMPEG4AAC,
    AVEncoderBitRateKey: NSNumber(integerLiteral: 128000),
    AVNumberOfChannelsKey: NSNumber(integerLiteral: 2),
    AVSampleRateKey: NSNumber(value: Float(44100))
]

exporter.export(progressHandler: { (progress) in
    print(progress)
}, completionHandler: { result in
    switch result {
    case .success(let status):
        switch status {
        case .completed:
            print("NextLevelSessionExporter, export completed, \(exporter.outputURL?.description ?? "")")
            break
        default:
            print("NextLevelSessionExporter, did not complete")
            break
        }
        break
    case .failure(let error):
        print("NextLevelSessionExporter, failed to export \(error)")
        break
    }
})

Documentation

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

Community

Resources

License

NextLevelSessionExporter is available under the MIT license, see the LICENSE file for more information.

Comments
  • Exported Video output green with audio

    Exported Video output green with audio

    I've attached the code used to setup the video configuration, any help would be appreciated.

    let encoder = NextLevelSessionExporter(withAsset: asset)
                            encoder.delegate = self
                            encoder.outputFileType = AVFileTypeMPEG4
                            encoder.optimizeForNetworkUse = true
    
                            let tmpURL = try! URL(fileURLWithPath: NSTemporaryDirectory(), isDirectory: true)
                                    .appendingPathComponent(ProcessInfo().globallyUniqueString)
                                    .appendingPathExtension("mp4")
    
                            encoder.outputURL = tmpURL
                            encoder.videoOutputConfiguration = [
                                AVVideoCodecKey: AVVideoCodecH264,
                                AVVideoHeightKey: CGFloat(640),
                                AVVideoWidthKey: CGFloat(352),
                                AVVideoScalingModeKey: AVVideoScalingModeResizeAspectFill,
                                AVVideoCompressionPropertiesKey: [
                                    AVVideoAverageBitRateKey: CGFloat(960*1000),
                                    AVVideoMaxKeyFrameIntervalKey: CGFloat(30)
                                ]
                            ]
                            encoder.audioOutputConfiguration = [
                                AVFormatIDKey: Int(kAudioFormatMPEG4AAC),
                                AVEncoderBitRateKey: 40000,
                                AVNumberOfChannelsKey: 1,
                                AVSampleRateKey: 16000
                            ]
    
    bug 
    opened by jjaybrown 15
  • [Investigating] 0.4.0 Upgrade crashing on export - only change: updated callback signature

    [Investigating] 0.4.0 Upgrade crashing on export - only change: updated callback signature

    Moving from 0.3.0 to 0.4.0, with my only change being the new callback function signature, it consistently started crashing on export. Tried a few sanity tests to make sure it wasn't device/encoding profile specific, but reproducible across everything i tried. haven't spent much time on this yet, but just opening for visibility. It must be something specific to my configuration that is causing problems. I'll go through the diff and get a example proj going with README example and work forward.

    Fatal Exception: NSInternalInconsistencyException
    *** -[AVAssetReaderAudioMixOutput copyNextSampleBuffer] cannot copy next sample buffer before adding this output to an instance of AVAssetReader (using -addOutput:) and calling -startReading on that asset reader
    
    Fatal Exception: NSInternalInconsistencyException
    0  CoreFoundation                 0x1f3f5eab8 (Missing)
    1  libobjc.A.dylib                0x1f3163d00 (Missing)
    2  AVFoundation                   0x1fa009cb4 (Missing)
    3  NextLevelSessionExporter       0x103703afc NextLevelSessionExporter.encode(readySamplesFromReaderOutput:toWriterInput:) + 423 (NextLevelSessionExporter.swift:423)
    4  NextLevelSessionExporter       0x103708700 partial apply for closure #5 in NextLevelSessionExporter.export(renderHandler:progressHandler:completionHandler:) + 276 (NextLevelSessionExporter.swift:276)
    5  NextLevelSessionExporter       0x1037031b8 thunk for @escaping @callee_guaranteed () -> () (<compiler-generated>)
    6  AVFoundation                   0x1fa02ac0c (Missing)
    7  libdispatch.dylib              0x1f396c308 (Missing)
    8  libdispatch.dylib              0x1f396d888 (Missing)
    9  libdispatch.dylib              0x1f3974dd4 (Missing)
    10 libdispatch.dylib              0x1f3975954 (Missing)
    11 libdispatch.dylib              0x1f397dcc0 (Missing)
    12 libsystem_pthread.dylib        0x1f3b69a98 (Missing)
    13 libsystem_pthread.dylib        0x1f3b6fdc4 (Missing)
    
    opened by rromanchuk 9
  • NextLevelSessionExporter, did not complete

    NextLevelSessionExporter, did not complete

    Even using the default project, it will not export, I just keep getting:

    "NextLevelSessionExporter, did not complete"

    I'm on the new Xcode 11 using Mojave 10.14.6

    opened by andrewgypsee 6
  • RenderHandler not called when exporting

    RenderHandler not called when exporting

    I'm trying to use the export method with the render handler in order to manipulate the output buffers with affects and filters however the handler never gets called.

           do {
                try exporter.export(renderHandler: { input, time, output in
                    let image = MTIImage(cvPixelBuffer: input, alphaType: .alphaIsOne)
                    let outputImage = MetalFilterProcessor.shared.applyFilters(for: clip.metaData, input: image, currentTime: time)
    
                    do {
                        try context.render(outputImage, to: output)
                    } catch {
                        print("Error applying filters")
                    }
    
                }, progressHandler: { progress in
                    print(progress)
                }) { status in
                    switch status {
                    case .completed:
                        print("video export completed")
                        break
                    case .cancelled:
                        print("video export cancelled")
                        break
                    default:
                        break
                    }
                }
            } catch {
                print("failed to export")
            }
    
    bug 
    opened by alexjameslittle 5
  • Disposing correctly

    Disposing correctly

    Hi I have managed to use your library to compress some videos... its working really well so thanks for the great library. I have a few of questions if you dont mind answering them.

    1. I haven't done much swift and don't have a great understanding of its garbage collection. Do we have to dispose or clear anything once the encoder has finished?

    2. In the completion handler I noticed that result has a success/failure. Both of which has a (enum?.. im not really sure what it is) .cancelled... When i manually cancel the request using exporter.cancelExport() it always goes in the switch in the .falure. Under what scenario would it go in the .sucess switch?

    completionHandler: { result in
                print("Hello IT HAS FINISHED")
                switch result {
                    case .success(let status):
                        switch status {
                        case .completed:
    
                            break
                        case .cancelled:
                            print("User cancelled request ")
                            break
                        default:
                  
                            break
                        }
                        break
                    
                    case .failure(let error as NextLevelSessionExporterError):
                        switch error {
                        case .cancelled:
                            print("User cancelled request ")
                            break
                        default:
                            break
                           
                    }
                    case .failure(let error):
                             break
    
    
    1. Does this use an MPEG LA patented algorithms and I am ok with using this in a commercial application?

    Thanks a lot :)

    question 
    opened by febg11 4
  • Preserve original orientation

    Preserve original orientation

    Hey @piemonte

    Im curious if this library preserves the original orientation of the video the it was captured. Im experience a problem with my own export method were videos captured on the native iOS camera app in portrait mode are exported in landscape. Does this lib prevent that?

    question 
    opened by otymartin 4
  • New release

    New release

    Would it be possible to release a new version? I'm interested by the Carthage support that was recently added, and I want to avoid pointing to master.

    Thank you

    opened by MartinMoizard 2
  • Can I export audio only from a mp4

    Can I export audio only from a mp4

    Hi @piemonte ,

    Can NextLevelSessionExporter be used to export only the audio from a video asset ? Specifically, I'm looking to export the audio tracks of a mp4 file to CoreAudio format.

    Thanks

    question 
    opened by cybercent 2
  • HEVC codec type not supported.

    HEVC codec type not supported.

    I wanted to convert video files with hevc codec, unfortunately, the framework is unable to convert files with the hevc codec. There is no video available after the conversion.

    Here is the configuration that I tried: Conversion Configuation

    opened by rabelhmd 1
  • Fix CVPixelBufferPoolCreatePixelBuffer result comparison crash

    Fix CVPixelBufferPoolCreatePixelBuffer result comparison crash

    Hello.

    I fixed the issue I found with the NextLevelSessionExporter when building the framework with Xcode 12.

    Using switch with it's default case with let result = CVPixelBufferPoolCreatePixelBuffer causing this exception when running app and using the exporter

    ** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: '*** -[AVAssetWriterInput appendSampleBuffer:] Cannot append sample buffer: Must start a session (using -[AVAssetWriter startSessionAtSourceTime:) first'

    I also changed switch result to if result == kCVReturnSuccess since we have nothing left to execute in default case.

    opened by russ-stamant 1
  • Cannot export the video to play in full screen

    Cannot export the video to play in full screen

    I'm recording video using AVCaptureMovieFileOutput and passing the file URL given by AVCaptureMovieFileOutput to NextLevelSessionExporter instance. I'm trying to export the video in a way that it takes up the whole device's screen to display video. It is working into the app, when I play the exported video using AVPreviewLayer it plays in full screen and takes up the whole device screen but as soon as I export the video into gallery then playing from gallery it does not plays into full screen and have black stripes above and below. Basically, I want to do just like snapchat does, when we save a snap-video from snapchat it is being played into full screen from gallery.

    func fileOutput(_ output: AVCaptureFileOutput, didFinishRecordingTo outputFileURL: URL, from connections: [AVCaptureConnection], error: Error?) {
            if let err = error as NSError?, err.code != -11810 { //-11810 = recording stopped when timelimit reached
                print("Error recording movie: \(err)")
            } else {
                let asset = AVAsset(url: outputFileURL)
                let exporter = NextLevelSessionExporter(withAsset: asset)
                exporter.outputFileType = AVFileType.mp4
                let tmpURL = URL(fileURLWithPath: NSTemporaryDirectory(), isDirectory: true)
                    .appendingPathComponent(ProcessInfo().globallyUniqueString)
                    .appendingPathExtension("mp4")
                exporter.outputURL = tmpURL
    
                let compressionDict: [String: Any] = [
                    AVVideoAverageBitRateKey: NSNumber(integerLiteral: 1100000),
                    AVVideoProfileLevelKey: AVVideoProfileLevelH264HighAutoLevel as String,
                ]
                let videoTrack = asset.tracks(withMediaType: .video).first
                exporter.videoOutputConfiguration = [
                    AVVideoCodecKey: AVVideoCodecType.h264,
                    AVVideoWidthKey: NSNumber(integerLiteral: Int(videoTrack?.naturalSize.height ?? 1080)),
                    AVVideoHeightKey: NSNumber(integerLiteral: Int(videoTrack?.naturalSize.width ?? 1920)),
                    AVVideoScalingModeKey: AVVideoScalingModeResizeAspectFill,
                    AVVideoCompressionPropertiesKey: compressionDict
                ]
                exporter.audioOutputConfiguration = [
                    AVFormatIDKey: kAudioFormatMPEG4AAC,
                    AVEncoderBitRateKey: NSNumber(integerLiteral: 128000),
                    AVNumberOfChannelsKey: NSNumber(integerLiteral: 2),
                    AVSampleRateKey: NSNumber(value: Float(44100))
                ]
    
                exporter.export(progressHandler: { (progress) in
                    print(progress)
                }, completionHandler: { [weak self] result in
                    guard let self = self else { return }
                    switch result {
                    case .success(let status):
                        switch status {
                        case .completed:
                            print("NextLevelSessionExporter, export completed, \(exporter.outputURL?.description ?? "")")
                            break
                        default:
                            print("NextLevelSessionExporter, did not complete")
                            break
                        }
                        break
                    case .failure(let error):
                        print("NextLevelSessionExporter, failed to export \(error)")
                        break
                    }
                })
                
            }
        }
    
    opened by rjt3662 1
  • dispatch_semaphore  Priority inversion problem

    dispatch_semaphore Priority inversion problem

    Thread Performance Checker: Thread running at QOS_CLASS_USER_INITIATED waiting on a lower QoS thread running at QOS_CLASS_DEFAULT that performed synchronous networking which can incur variable delays. Investigate ways to avoid priority inversions

    opened by huanglins 1
  • Buffers in pool may not always point at the video compositors output

    Buffers in pool may not always point at the video compositors output

    We received a report of black frames in an applications video content once it was encoded with NextLevelSessionExporter.

    Investigation revealed a similar issue as https://github.com/NextLevel/NextLevelSessionExporter/issues/38.

    It appears NextLevelSessionExporter is pulling buffers from the pool that was created, and sending those buffers back to the API. The assumption a buffer pulled from that pool will contain the output of the Metal video compositor is not always correct.

    This change will pass the pixelBuffer directly, or use the toBuffer if a renderHandler exists. It resolves black frames in video content in our testing, @GrandPoohBear you may want to give it a try.

    opened by Developer-Ecosystem-Engineering 2
  • Exported videos missing video track (audio only)

    Exported videos missing video track (audio only)

    In some cases, we have seen videos that are exported by NextLevelSessionExporter that seem to consistently drop the video tracks entirely, leaving just an audio track in the output file. Luckily, it's fairly easy to detect the problem - looking at the ratio of file sizes between compressed and uncompressed files leaves completely silly compression ratios.

    We're working on getting a reliable repro case, but it's possible it has something to do with videos that came from Snapchat.

    When I know more, I can post back, but wondering if others have seen anything similar, and if there's a way to prevent it from happening?

    opened by GrandPoohBear 2
  • some videos are unable to compress with the canceled error message.

    some videos are unable to compress with the canceled error message.

    some videos are unable to compress with the canceled error message. The below video always fails with the canceled error message. why?

    https://sample-videos.com/video123/mp4/720/big_buck_bunny_720p_30mb.mp4

    opened by numandev1 4
  • iOS 14.5 Sometimes crash

    iOS 14.5 Sometimes crash

    Hello, I use your library for video export using CoreAnimation Tool. But on the last iOS update(14.5) I noticed that exporter finished export with error: Error Domain=AVFoundationErrorDomain Code=-11819 "Cannot Complete Action" UserInfo={NSLocalizedDescription=Cannot Complete Action, NSLocalizedRecoverySuggestion=Try again later.} . I have found on apple forums: https://developer.apple.com/forums/thread/679862 it sounds similar. Do you know how can I fix that error ? Thank you

    opened by juraam 0
Owner
NextLevel
Camera Platform in Swift
NextLevel
▶️ 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. Looking for an obj-c video player? Check out PBJVideoPlayer (obj-c). Looking for

patrick piemonte 2k Jan 2, 2023
MobilePlayer - A powerful and completely customizable media player for iOS

MobilePlayer A powerful and completely customizable media player for iOS. Table of Contents Features Installation Usage Customization Skinning Showing

Sahin Boydas 3k Jan 2, 2023
A powerful and completely customizable media player for iOS

MobilePlayer A powerful and completely customizable media player for iOS. Table of Contents Features Installation Usage Customization Skinning Showing

Sahin Boydas 3k Jan 2, 2023
VLC media player

VLC media player VLC is a libre and open source media player and multimedia engine, focused on playing everything, and running everywhere. VLC can pla

VideoLAN 10.1k Dec 24, 2022
A high-performance, flexible, and easy-to-use Video compressor library written by Swift.

FYVideoCompressor A high-performance, flexible and easy to use Video compressor library written by Swift. Using hardware-accelerator APIs in AVFoundat

null 30 Dec 30, 2022
360 video player for iOS written in swift - a subset of SceneKit that works

DDDKit An open source library to support 360 videos and pictures. It's designed as a generic 3D library that you can use for much more! Example of use

Guillaume Sabran 123 Aug 9, 2022
Swift library for embedding and controlling YouTube videos in your iOS applications via WKWebView!

YouTubePlayer Embed and control YouTube videos in your iOS applications! Neato, right? Let's see how it works. 0.7.0 Update: WKWebView breaking change

Giles Van Gruisen 825 Jan 3, 2023
An iOS App which has written using Vision franework

It's an iOS App which has written using Vision franework. It's written purely in Swift without using 3rd party frameworks.

iMamad 1 May 10, 2022
Camera and Microphone streaming library via RTMP, HLS for iOS, macOS, tvOS.

HaishinKit (formerly lf) Camera and Microphone streaming library via RTMP, HLS for iOS, macOS, tvOS. Issuesの言語は、日本語が分かる方は日本語でお願いします! Sponsored with ??

shogo4405 2.4k Dec 29, 2022
A Swift library to upload video files to api.video platform.

api.video IOS video uploader api.video is the video infrastructure for product builders. Lightning fast video APIs for integrating, scaling, and manag

api.video 7 Dec 9, 2022
SuperPlayer is a library to wrap AVPlayer with Composable Architecture.

SuperPlayer is a library to wrap AVPlayer with Composable Architecture. It can be used in SwiftUI and UIKit.

Tokopedia 13 Dec 21, 2022
High-performance and flexible video editing and effects framework, based on AVFoundation and Metal.

High-performance and flexible video editing and effects framework, based on AVFoundation and Metal.

BearRuan 650 Dec 30, 2022
Yattee: video player for Invidious and Piped built for iOS 15, tvOS 15 and macOS Monterey

Video player with support for Invidious and Piped instances built for iOS 15, tvOS 15 and macOS Monterey.

Yattee 1k Dec 27, 2022
Yattee: video player for Invidious and Piped built for iOS, tvOS and macOS

Video player for Invidious and Piped instances built for iOS, tvOS and macOS. Features Native user interface built with SwiftUI Multiple instances and

Yattee 1.1k Jan 8, 2023
Collection of Swift/iOS-related conference videos. A demo project for SuperArc framework - building modular iOS apps with a µComponent architecture.

SwiftCommunity Beta version is available at TestFlight Collection of Swift/iOS-related conference videos. This project serves as a showcase for the Su

SuperArcSwift 52 Dec 2, 2022
MMPlayerView - Custom AVPlayerLayer on view and transition player with good effect like youtube and facebook

MMPlayerView Demo-Swift List / Shrink / Transition / Landscape MMPlayerLayer ex. use when change player view frequently like tableView / collectionVie

Millman Yang 724 Nov 24, 2022
iOS video player for trailer. You can customize layout for the control panel. Support PiP and DRM.

iOS video player for trailer. You can customize layout for the control panel. Support PiP and DRM.

Abe Wang 11 Nov 7, 2022
A simple iOS app similar to iTunes where you can view details of your favorite movies, songs and audio books.

Popcorn Adventure This is an iOS app developed by Arthur Tristan M. Ramos who has taken the Appetiser iOS Coding Challenge. Design Pattern The design

Arthur Tristan M. Ramos 0 Dec 11, 2021
YouTube video player for iOS, tvOS and macOS

About XCDYouTubeKit is a YouTube video player for iOS, tvOS and macOS. Are you enjoying XCDYouTubeKit? You can say thank you with a tweet. I am also a

Cédric Luthi 2.9k Jan 7, 2023