美文网首页
Swift 音视频编辑Demo

Swift 音视频编辑Demo

作者: CYC666 | 来源:发表于2023-02-11 20:44 被阅读0次

实现的功能:视频1的视频 + 视频2的音频,并导出视频文件

//
//  ViewController.swift
//  MovieEdit
//
//  Created by caoyicheng on 2023/2/12.
//

import UIKit
import AVKit

let kScreenWidth = UIScreen.main.bounds.width
let kScreenHeight = UIScreen.main.bounds.height

class ViewController: UIViewController {
    
    var player = AVPlayer()
    var showView = UIView()

    override func viewDidLoad() {
        super.viewDidLoad()
        
        
        let view1 = UIView.init(frame: CGRect.init(x: 0, y: 100, width: kScreenWidth, height: kScreenWidth*0.5))
        view1.backgroundColor = .systemPink
        self.view.addSubview(view1)
        self.showView = view1
        
        let btn1 = UIButton.init(frame: CGRect.init(x: (kScreenWidth - 200)/2.0, y: view1.c_bottom() + 50, width: 200, height: 50))
        btn1.setTitle("添加视频1", for: .normal)
        btn1.setTitleColor(.white, for: .normal)
        btn1.titleLabel?.font = .systemFont(ofSize: 16)
        btn1.backgroundColor = .systemBlue
        btn1.c_radius(radius: btn1.c_height()/2.0)
        btn1.addTarget(self, action: #selector(button1Action(btn:)), for: .touchUpInside)
        self.view.addSubview(btn1)
        
        let btn2 = UIButton.init(frame: CGRect.init(x: (kScreenWidth - 200)/2.0, y: btn1.c_bottom() + 30, width: 200, height: 50))
        btn2.setTitle("添加视频2", for: .normal)
        btn2.setTitleColor(.white, for: .normal)
        btn2.titleLabel?.font = .systemFont(ofSize: 16)
        btn2.backgroundColor = .systemBlue
        btn2.c_radius(radius: btn2.c_height()/2.0)
        btn2.addTarget(self, action: #selector(button2Action(btn:)), for: .touchUpInside)
        self.view.addSubview(btn2)
        
        let btn3 = UIButton.init(frame: CGRect.init(x: (kScreenWidth - 200)/2.0, y: btn2.c_bottom() + 30, width: 200, height: 50))
        btn3.setTitle("播放视频", for: .normal)
        btn3.setTitleColor(.white, for: .normal)
        btn3.titleLabel?.font = .systemFont(ofSize: 16)
        btn3.backgroundColor = .systemBlue
        btn3.c_radius(radius: btn3.c_height()/2.0)
        btn3.addTarget(self, action: #selector(button3Action(btn:)), for: .touchUpInside)
        self.view.addSubview(btn3)
        
        
    }

    // MARK: 添加视频1
    @objc func button1Action(btn: UIButton) {
        
        // 任务:视频1的视频 + 视频2的音频
        
        // 1、加载视频资源
        let path1 = Bundle.main.path(forResource: "movie1", ofType: "mov")
        let videoAsset1 = AVAsset.init(url: URL.init(fileURLWithPath: path1!))
        let path2 = Bundle.main.path(forResource: "movie2", ofType: "mov")
        let videoAsset2 = AVAsset.init(url: URL.init(fileURLWithPath: path2!))
        
        // 2、取出视频轨道、音频轨道
        let videoAssetTrack = videoAsset1.tracks(withMediaType: .video).first
        let audioAssetTrack = videoAsset2.tracks(withMediaType: .audio).first
        
        // 3、创建工程,将素材的轨道数据导入到工程文件的轨道中
        let mutableComposition = AVMutableComposition.init()
        let videoTrack = mutableComposition.addMutableTrack(withMediaType: .video, preferredTrackID: kCMPersistentTrackID_Invalid)
        let audioTrack = mutableComposition.addMutableTrack(withMediaType: .audio, preferredTrackID: kCMPersistentTrackID_Invalid)
        
        do {
            
            try videoTrack!.insertTimeRange(.init(start: .zero, end: videoAsset1.duration), of: videoAssetTrack!, at: .zero)
            try audioTrack!.insertTimeRange(.init(start: .zero, end: videoAsset2.duration), of: audioAssetTrack!, at: .zero)
            
//            // 4、计算需要裁剪的头和尾的range,然后将音频轨道和视频轨道都进行裁剪
//            let start = CMTimeMakeWithSeconds(1, preferredTimescale: videoAsset1.duration.timescale)
//            let end = CMTimeMakeWithSeconds(3, preferredTimescale: videoAsset1.duration.timescale)
//            let duration = CMTimeMakeWithSeconds(1, preferredTimescale: videoAsset1.duration.timescale)
//            let deleteRange1 = CMTimeRangeMake(start: .zero, duration: start)
//            let deleteRange2 = CMTimeRangeMake(start: end, duration: duration)
//            videoTrack!.removeTimeRange(deleteRange1)
//            videoTrack!.removeTimeRange(deleteRange2)
//            audioTrack!.removeTimeRange(deleteRange1)
//            audioTrack!.removeTimeRange(deleteRange2)
            
//            // 5、我们已经将工程文件中的视频进行了裁剪,我们可以直接使用AVPlayer进行播放看裁剪成功没有
//            let item = AVPlayerItem.init(asset: mutableComposition)
//            self.player = AVPlayer.init(playerItem: item)
//            let playerLayer = AVPlayerLayer.init(player: self.player)
//            playerLayer.frame = self.showView.bounds
//            self.showView.layer.addSublayer(playerLayer)
//            self.player.play()
            
            

            // 6、使用AVAssetExportSession将工程文件转码导出
            let exportSession = AVAssetExportSession.init(asset: mutableComposition, presetName: AVAssetExportPresetPassthrough)
            if let savePath = self.getSavePath() {
                
                let outPath = NSURL.fileURL(withPath: savePath)
                exportSession!.outputURL = outPath
                exportSession!.outputFileType = .mp4
                exportSession!.exportAsynchronously {
                    
                    if exportSession!.status == .failed {
                        
                        print("失败")
                        print(exportSession!.error!.localizedDescription)
                    } else if exportSession!.status == .cancelled {
                        
                        print("取消")
                    } else if exportSession!.status == .completed {
                        
                        print("完成")
                        print(savePath)
                    } else {
                        
                        print("未知")
                    }
                    
                }
            } else {
                
                print("获取保存路径失败")
            }
            
            
            
        } catch {
            
            print(error)
        }
    }
    
    // MARK: 添加视频2
    @objc func button2Action(btn: UIButton) {
        
        
    }
    
    // MARK: 播放视频
    @objc func button3Action(btn: UIButton) {
        
        // 播放视频
        let path = Bundle.main.path(forResource: "movie1", ofType: "mov")
        let playerItem = AVPlayerItem.init(url: URL.init(fileURLWithPath: path!))
        self.player = AVPlayer.init(playerItem: playerItem)
        let playerLayer = AVPlayerLayer.init(player: self.player)
        playerLayer.frame = self.showView.bounds
        self.showView.layer.addSublayer(playerLayer)
        self.player.play()
    }

    // MARK: 获取保存路劲
    @objc func getSavePath() -> String? {
        
        
        let savePath = String.init(format: "%@/DraftVideo", NSSearchPathForDirectoriesInDomains(.cachesDirectory, .userDomainMask, true)[0])
        
        do {
            
            let fileManager = FileManager.default
            
            if fileManager.fileExists(atPath: savePath) == false {
                
                // 文件夹不存在,则创建
                try fileManager.createDirectory(at: URL(fileURLWithPath: savePath), withIntermediateDirectories: true, attributes: nil)
                
            } else {
                
                // 文件夹存在
            }
            
            let videoPath = String.init(format: "%@/%.0f.mp4", savePath, Date().timeIntervalSince1970)
            return videoPath
            
        } catch {
            
        }
        
        return nil
    }
    
}


相关文章

网友评论

      本文标题:Swift 音视频编辑Demo

      本文链接:https://www.haomeiwen.com/subject/fvdrkdtx.html