|
@@ -69,10 +69,13 @@ class PQStuckPointPublicController: PQBaseViewController {
|
|
|
// 导出的开始的开始和结束时间
|
|
|
var playeTimeRange: CMTimeRange = CMTimeRange()
|
|
|
|
|
|
- //add by ak 保存系统相册使用的变量
|
|
|
- // 导出保存相册视频工具类
|
|
|
- private var saveMovieExporter: PQCompositionExporter!
|
|
|
- private var saveMovieExportLocalURL: URL? // 导出的地址
|
|
|
+ //---------------------------add by ak 保存系统相册使用的变量
|
|
|
+ // 导出有水印的正片
|
|
|
+ private var watermarkMovieExporter: PQCompositionExporter!
|
|
|
+ private var watermarkMovieLocalURL: URL? // 导出的地址
|
|
|
+ // 导出片尾
|
|
|
+ private var endMovieExporter: PQCompositionExporter!
|
|
|
+ private var endMovieLocalURL: URL? // 导出的地址
|
|
|
//----------------------------
|
|
|
|
|
|
// 预览大小
|
|
@@ -767,7 +770,7 @@ extension PQStuckPointPublicController {
|
|
|
//导出不带水印的正片
|
|
|
self?.beginExport(inputAsset: asset)
|
|
|
//导出带水印的正片
|
|
|
- self?.beginExportSaveMovie(inputAsset:asset)
|
|
|
+ self?.beginExportWatermarkMovie(inputAsset:asset)
|
|
|
}else{
|
|
|
cShowHUB(superView: self?.view, msg: "合成失败请重试。")
|
|
|
}
|
|
@@ -870,7 +873,7 @@ extension PQStuckPointPublicController {
|
|
|
/// - Returns: <#description#>
|
|
|
func saveStuckPointVideo() {
|
|
|
|
|
|
- if(saveMovieExportLocalURL == nil){
|
|
|
+ if(watermarkMovieLocalURL == nil){
|
|
|
BFLog(message: "保存相册的视频导出地址无效!!!")
|
|
|
return
|
|
|
}
|
|
@@ -878,7 +881,7 @@ extension PQStuckPointPublicController {
|
|
|
if authStatus == .authorized {
|
|
|
let photoLibrary = PHPhotoLibrary.shared()
|
|
|
photoLibrary.performChanges({ [weak self] in
|
|
|
- PHAssetChangeRequest.creationRequestForAssetFromVideo(atFileURL: (self?.saveMovieExportLocalURL)!)
|
|
|
+ PHAssetChangeRequest.creationRequestForAssetFromVideo(atFileURL: (self?.watermarkMovieLocalURL)!)
|
|
|
}) { [weak self] isFinished, _ in
|
|
|
DispatchQueue.main.async { [weak self] in
|
|
|
if self?.view != nil {
|
|
@@ -1535,7 +1538,8 @@ extension PQStuckPointPublicController {
|
|
|
|
|
|
// MARK: - 导出带水印+片尾的视频相关方法
|
|
|
extension PQStuckPointPublicController {
|
|
|
- func beginExportSaveMovie(inputAsset: AVURLAsset!) {
|
|
|
+ //导出有水印的正片子
|
|
|
+ func beginExportWatermarkMovie(inputAsset: AVURLAsset!) {
|
|
|
if !(editProjectModel?.sData?.sections != nil && (editProjectModel?.sData?.sections.count ?? 0) > 0) {
|
|
|
BFLog(message: "项目段落错误❌")
|
|
|
return
|
|
@@ -1550,8 +1554,8 @@ extension PQStuckPointPublicController {
|
|
|
let outPutMP4URL = URL(fileURLWithPath: outPutMP4Path)
|
|
|
BFLog(message: "导出视频地址 \(outPutMP4URL)")
|
|
|
|
|
|
- saveMovieExporter = PQCompositionExporter(asset: inputAsset, videoComposition: nil, audioMix: nil, filters: nil, stickers: mStickers, animationTool: nil, exportURL: outPutMP4URL)
|
|
|
- saveMovieExporter.isAddWatermark = true
|
|
|
+ watermarkMovieExporter = PQCompositionExporter(asset: inputAsset, videoComposition: nil, audioMix: nil, filters: nil, stickers: mStickers, animationTool: nil, exportURL: outPutMP4URL)
|
|
|
+ watermarkMovieExporter.isAddWatermark = true
|
|
|
var orgeBitRate = (editProjectModel?.sData?.videoMetaData?.videoWidth ?? 0) * (editProjectModel?.sData?.videoMetaData?.videoHeight ?? 0) * 3
|
|
|
|
|
|
if mStickers != nil {
|
|
@@ -1567,26 +1571,100 @@ extension PQStuckPointPublicController {
|
|
|
}
|
|
|
}
|
|
|
BFLog(message: "导出设置的码率为:\(orgeBitRate)")
|
|
|
- saveMovieExporter.showGaussianBlur = true
|
|
|
- if saveMovieExporter.prepare(videoSize: CGSize(width: editProjectModel?.sData?.videoMetaData?.videoWidth ?? 0, height: editProjectModel?.sData?.videoMetaData?.videoHeight ?? 0), videoAverageBitRate: orgeBitRate) {
|
|
|
+ watermarkMovieExporter.showGaussianBlur = true
|
|
|
+ if watermarkMovieExporter.prepare(videoSize: CGSize(width: editProjectModel?.sData?.videoMetaData?.videoWidth ?? 0, height: editProjectModel?.sData?.videoMetaData?.videoHeight ?? 0), videoAverageBitRate: orgeBitRate) {
|
|
|
BFLog(message: "开始导出 \(String(describing: playeTimeRange.start)) 结束 \(String(describing: playeTimeRange.end))")
|
|
|
- saveMovieExporter.start(playeTimeRange: playeTimeRange)
|
|
|
+ watermarkMovieExporter.start(playeTimeRange: playeTimeRange)
|
|
|
BFLog(message: "开始导出")
|
|
|
}
|
|
|
- saveMovieExporter.progressClosure = { [weak self] _, _, progress in
|
|
|
+ watermarkMovieExporter.progressClosure = { [weak self] _, _, progress in
|
|
|
BFLog(message: "带水印的合成进度 \(progress) ")
|
|
|
|
|
|
}
|
|
|
- saveMovieExporter.completion = { [weak self] url in
|
|
|
+ watermarkMovieExporter.completion = { [weak self] url in
|
|
|
BFLog(message: "有水印的视频导出完成: \(url) 生成视频时长为:\(CMTimeGetSeconds(AVAsset(url: url).duration))")
|
|
|
|
|
|
// 导出完成后取消导出
|
|
|
- if self?.saveMovieExporter != nil {
|
|
|
- self?.saveMovieExporter.cancel()
|
|
|
+ if self?.watermarkMovieExporter != nil {
|
|
|
+ self?.watermarkMovieExporter.cancel()
|
|
|
}
|
|
|
|
|
|
- self?.saveMovieExportLocalURL = url
|
|
|
+ self?.watermarkMovieLocalURL = url
|
|
|
+
|
|
|
+ //开始导出片尾
|
|
|
+ self?.beginExportEndMovie()
|
|
|
|
|
|
}
|
|
|
}
|
|
|
+ //导出片尾视频
|
|
|
+ func beginExportEndMovie() {
|
|
|
+ if !(editProjectModel?.sData?.sections != nil && (editProjectModel?.sData?.sections.count ?? 0) > 0) {
|
|
|
+ BFLog(message: "项目段落错误❌")
|
|
|
+ return
|
|
|
+ }
|
|
|
+ // 输出视频地址
|
|
|
+ var outPutMP4Path = exportVideosDirectory
|
|
|
+ if !directoryIsExists(dicPath: outPutMP4Path) {
|
|
|
+ BFLog(message: "文件夹不存在")
|
|
|
+ createDirectory(path: outPutMP4Path)
|
|
|
+ }
|
|
|
+ outPutMP4Path.append("endMovie_\(String.qe.timestamp()).mp4")
|
|
|
+ let outPutMP4URL = URL(fileURLWithPath: outPutMP4Path)
|
|
|
+ BFLog(message: "导出视频地址 \(outPutMP4URL)")
|
|
|
+
|
|
|
+ var orgeBitRate = (editProjectModel?.sData?.videoMetaData?.videoWidth ?? 0) * (editProjectModel?.sData?.videoMetaData?.videoHeight ?? 0) * 3
|
|
|
+
|
|
|
+ //片尾的视频素材地址
|
|
|
+ let moveResPath = Bundle().BF_mainbundle().path(forResource: "endMovieA", ofType: "mp4")
|
|
|
+ if(moveResPath?.count ?? 0 == 0){
|
|
|
+ BFLog(message: "片尾的视频素材地址无效!!!")
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ let movieAsset = AVURLAsset(url: URL(fileURLWithPath: moveResPath!), options: avAssertOptions)
|
|
|
+ let cbr = movieAsset.tracks(withMediaType: .video).first?.estimatedDataRate
|
|
|
+ BFLog(message: "cbr is\(cbr ?? 0)")
|
|
|
+ if Int(cbr ?? 0) > orgeBitRate {
|
|
|
+ orgeBitRate = Int(cbr ?? 0)
|
|
|
+ }
|
|
|
+ BFLog(message: "导出设置的码率为:\(orgeBitRate)")
|
|
|
+ //视频素材
|
|
|
+ let stickerInfo:PQEditVisionTrackMaterialsModel = PQEditVisionTrackMaterialsModel.init()
|
|
|
+ stickerInfo.type = StickerType.VIDEO.rawValue
|
|
|
+ stickerInfo.locationPath = moveResPath ?? ""
|
|
|
+ stickerInfo.timelineIn = 0
|
|
|
+ stickerInfo.timelineOut = CMTimeGetSeconds(movieAsset.duration)
|
|
|
+ stickerInfo.model_in = stickerInfo.timelineIn
|
|
|
+ stickerInfo.out = stickerInfo.timelineOut
|
|
|
+ stickerInfo.canvasFillType = stickerContentMode.aspectFitStr.rawValue
|
|
|
+
|
|
|
+ let soundResPath = Bundle().BF_mainbundle().path(forResource: "endMovieSound", ofType: "mp3")
|
|
|
+
|
|
|
+ let soundAsset = AVURLAsset(url: URL(fileURLWithPath: soundResPath ?? ""), options: nil)
|
|
|
+ endMovieExporter = PQCompositionExporter(asset: soundAsset, videoComposition: nil, audioMix: nil, filters: nil, stickers: [stickerInfo], animationTool: nil, exportURL: outPutMP4URL)
|
|
|
+
|
|
|
+ endMovieExporter.showGaussianBlur = true
|
|
|
+ if endMovieExporter.prepare(videoSize: CGSize(width: editProjectModel?.sData?.videoMetaData?.videoWidth ?? 0, height: editProjectModel?.sData?.videoMetaData?.videoHeight ?? 0), videoAverageBitRate: orgeBitRate) {
|
|
|
+
|
|
|
+ endMovieExporter.start(playeTimeRange: CMTimeRange.init(start: CMTime.zero, duration: CMTimeMakeWithSeconds(Float64(stickerInfo.out), preferredTimescale: BASE_FILTER_TIMESCALE)))
|
|
|
+ BFLog(message: "开始导出")
|
|
|
+ }
|
|
|
+ endMovieExporter.progressClosure = { [weak self] _, _, progress in
|
|
|
+ BFLog(message: "片尾合成进度 \(progress) ")
|
|
|
+
|
|
|
+ }
|
|
|
+ endMovieExporter.completion = { [weak self] url in
|
|
|
+ BFLog(message: "片尾的视频导出完成: \(url) 生成视频时长为:\(CMTimeGetSeconds(AVAsset(url: url).duration))")
|
|
|
+
|
|
|
+ // 导出完成后取消导出
|
|
|
+ if self?.endMovieExporter != nil {
|
|
|
+ self?.endMovieExporter.cancel()
|
|
|
+ }
|
|
|
+ self?.endMovieLocalURL = url
|
|
|
+
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
}
|