161 lines
6.2 KiB
Swift
161 lines
6.2 KiB
Swift
//
|
||
// PlayContoller6.swift
|
||
// tdvideo
|
||
//
|
||
// Created by mac on 2024/2/4.
|
||
//
|
||
|
||
import UIKit
|
||
import AVFoundation
|
||
import CoreImage
|
||
import Foundation
|
||
import Observation
|
||
import VideoToolbox
|
||
|
||
|
||
class PlayContoller6: UIViewController {
|
||
private var player: AVPlayer!
|
||
private var playerLayer: AVPlayerLayer!
|
||
private var exportButton: UIButton!
|
||
|
||
|
||
|
||
override func viewDidLoad() {
|
||
super.viewDidLoad()
|
||
view.backgroundColor = UIColor.brown
|
||
setupPlayer()
|
||
setupExportButton()
|
||
}
|
||
|
||
private func setupPlayer() {
|
||
|
||
let path = Bundle.main.path(forResource: "IMG_0071", ofType: "MOV")
|
||
let videoURL = URL.init(filePath: path!)
|
||
let playerItem = AVPlayerItem(url: videoURL)
|
||
player = AVPlayer(playerItem: playerItem)
|
||
playerLayer = AVPlayerLayer(player: player)
|
||
playerLayer.frame = CGRect(x: 0, y: 0, width: view.bounds.width, height: view.bounds.height - 100)
|
||
view.layer.addSublayer(playerLayer)
|
||
player.play()
|
||
}
|
||
|
||
private func setupExportButton() {
|
||
exportButton = UIButton(type: .system)
|
||
exportButton.setTitleColor(UIColor.white, for: UIControl.State.normal)
|
||
exportButton.setTitle("导出", for: .normal)
|
||
exportButton.frame = CGRect(x: 0, y: view.bounds.height - 260, width: view.bounds.width, height: 100)
|
||
exportButton.addTarget(self, action: #selector(exportButtonTapped), for: .touchUpInside)
|
||
view.addSubview(exportButton)
|
||
}
|
||
|
||
@objc private func exportButtonTapped() {
|
||
let path = Bundle.main.path(forResource: "IMG_0071", ofType: "MOV")
|
||
let videoURL = URL.init(filePath: path!)
|
||
let documentsDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
|
||
let outputURL = documentsDirectory.appendingPathComponent("output_path.mp4")
|
||
|
||
do {
|
||
try FileManager.default.removeItem(atPath: outputURL.path)
|
||
print("视频文件删除成功")
|
||
} catch {
|
||
print("删除视频文件出错:\(error)")
|
||
}
|
||
|
||
let width = 1280
|
||
let height = 720
|
||
let dataRate = 5000000
|
||
let horizontalDisparity: Float = 0.0
|
||
let horizontalFieldOfView: Float = 90.0
|
||
|
||
exportVideo(url: videoURL, outputURL: outputURL, width: width, height: height, dataRate: dataRate, horizontalDisparity: horizontalDisparity, horizontalFieldOfView: horizontalFieldOfView) { exportedAsset in
|
||
// 处理导出的新AVAsset对象
|
||
// 在这里可以进行进一步的操作,比如播放导出的视频
|
||
DispatchQueue.main.async {
|
||
let exportedPlayerItem = AVPlayerItem(asset: exportedAsset!)
|
||
self.player.replaceCurrentItem(with: exportedPlayerItem)
|
||
self.player.play()
|
||
}
|
||
}
|
||
}
|
||
|
||
private func exportVideo(url: URL, outputURL: URL, width: Int, height: Int, dataRate: Int, horizontalDisparity: Float, horizontalFieldOfView: Float, completion: @escaping (AVAsset?) -> Void) {
|
||
let asset = AVAsset(url: url)
|
||
|
||
guard let exportSession = AVAssetExportSession(asset: asset, presetName: AVAssetExportPresetPassthrough) else {
|
||
print("Failed to create export session")
|
||
completion(nil)
|
||
return
|
||
}
|
||
|
||
let composition = AVMutableComposition()
|
||
let videoTrack = composition.addMutableTrack(withMediaType: .video, preferredTrackID: kCMPersistentTrackID_Invalid)
|
||
|
||
guard let assetTrack = asset.tracks(withMediaType: .video).first else {
|
||
print("Failed to get video track from asset")
|
||
completion(nil)
|
||
return
|
||
}
|
||
|
||
do {
|
||
try videoTrack?.insertTimeRange(CMTimeRange(start: .zero, duration: asset.duration), of: assetTrack, at: .zero)
|
||
} catch {
|
||
print("Failed to insert video track into composition")
|
||
completion(nil)
|
||
return
|
||
}
|
||
|
||
var videoSettings = AVOutputSettingsAssistant(preset: .mvhevc1440x1440)?.videoSettings
|
||
videoSettings?[AVVideoWidthKey] = width
|
||
videoSettings?[AVVideoHeightKey] = height
|
||
var compressionProperties = videoSettings?[AVVideoCompressionPropertiesKey] as! [String: Any]
|
||
compressionProperties[AVVideoAverageBitRateKey] = dataRate
|
||
compressionProperties[kVTCompressionPropertyKey_HorizontalDisparityAdjustment as String] = horizontalDisparity
|
||
compressionProperties[kCMFormatDescriptionExtension_HorizontalFieldOfView as String] = horizontalFieldOfView
|
||
compressionProperties[kCMFormatDescriptionExtension_HorizontalFieldOfView as String] = 180.0
|
||
|
||
videoSettings?[AVVideoCompressionPropertiesKey] = compressionProperties
|
||
|
||
let writerInput = AVAssetWriterInput(mediaType: .video, outputSettings: videoSettings)
|
||
writerInput.expectsMediaDataInRealTime = false
|
||
|
||
guard let writer = try? AVAssetWriter(outputURL: outputURL, fileType: AVFileType.mp4) else {
|
||
print("Failed to create AVAssetWriter")
|
||
completion(nil)
|
||
return
|
||
}
|
||
|
||
writer.add(writerInput)
|
||
|
||
guard let assetExportSession = exportSession as? AVAssetExportSession else {
|
||
print("Failed to cast export session to AVAssetExportSession")
|
||
completion(nil)
|
||
return
|
||
}
|
||
|
||
assetExportSession.videoComposition = AVMutableVideoComposition(propertiesOf: composition)
|
||
assetExportSession.outputFileType = AVFileType.mp4
|
||
assetExportSession.outputURL = outputURL
|
||
|
||
assetExportSession.exportAsynchronously {
|
||
switch assetExportSession.status {
|
||
case .completed:
|
||
let exportedAsset = AVAsset(url: outputURL)
|
||
completion(exportedAsset)
|
||
case .failed:
|
||
if let error = assetExportSession.error {
|
||
print("Export failed with error: \(error.localizedDescription)")
|
||
} else {
|
||
print("Export failed")
|
||
}
|
||
completion(nil)
|
||
case .cancelled:
|
||
print("Export cancelled")
|
||
completion(nil)
|
||
default:
|
||
break
|
||
}
|
||
}
|
||
}
|
||
|
||
}
|