Wallpaper_Home/wallpaper_project/Home/C/WA_LiveVideoVC.swift
2024-08-19 14:40:12 +08:00

611 lines
24 KiB
Swift
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// WA_LiveVideoVC.swift
// wallpaper_project
import UIKit
import AVFoundation
import MobileCoreServices
import FLAnimatedImage
import Photos
import PhotosUI
import SVProgressHUD
import Lottie
import AppLovinSDK
import Alamofire
import FirebaseRemoteConfig
import MTGSDKNewInterstitial
import MTGSDKBidding
import MTGSDK
import AnyThinkInterstitial
struct FilePaths {
//
static let documentsPath : AnyObject = NSSearchPathForDirectoriesInDomains(.cachesDirectory,.userDomainMask,true)[0] as AnyObject
struct VidToLive {
//
static var livePath = FilePaths.documentsPath.appending("/")
}
}
class WA_LiveVideoVC: WA_RootVC {
@IBOutlet weak var bgView: UIView!
@IBOutlet weak var tipLabel: UILabel!
var model = WA_3DModel()
var livePhotoView = PHLivePhotoView()
let activityView = UIActivityIndicatorView()
let btn = UIButton()
// let bgView = UIView()
var sizi:CGSize?
let Retrybtn = UIButton()
private var animationView: LottieAnimationView?
var animationDuration: TimeInterval = 1.0
var workProgress: Float = 0.0
var remoteConfig: RemoteConfig!
var isadshow:Bool = false
var bidToken:String?
var newInterstitialAdManager:MTGNewInterstitialBidAdManager?
override func viewDidLoad() {
super.viewDidLoad()
livePhotoView.frame = CGRect(x: 0, y: 0, width: Screen_Width, height: screenHeight);
btn.setImage(UIImage(named: "back_black"), for: .normal)
btn.backgroundColor = .white
btn.addTarget(self, action: #selector(buttonTapped), for: .touchUpInside) //
btn.layer.cornerRadius = 20
self.view.addSubview(self.livePhotoView)
self.livePhotoView.addSubview(btn)
btn.snp.makeConstraints { make in
make.left.equalTo(livePhotoView).offset(20)
make.top.equalTo(livePhotoView).offset(50)
make.height.equalTo(40)
make.width.equalTo(40)
}
Retrybtn.setTitle("Retry", for: .normal)
Retrybtn.setTitleColor(.white, for: .normal)
Retrybtn.backgroundColor = .black
Retrybtn.addTarget(self, action: #selector(Retrybtntapped), for: .touchUpInside)
Retrybtn.layer.cornerRadius = 10
Retrybtn.isHidden = true
self.livePhotoView.addSubview(Retrybtn)
Retrybtn.snp.makeConstraints { make in
make.centerX.equalTo(livePhotoView)
make.centerY.equalTo(livePhotoView)
make.height.equalTo(40)
make.width.equalTo(80)
}
animationView = .init(name: "loadProgress")
animationView!.frame = CGRect(x: 0, y: 100, width: Int(Screen_Width), height: Int(Screen_height) - 100)
animationView!.contentMode = .scaleAspectFit
// animationView!.loopMode = .loop
animationView!.loopMode = .autoReverse
self.livePhotoView.addSubview(animationView!)
// animationView!.play()
self.animationView!.currentProgress = 0.1
animationView!.sendSubviewToBack(btn)
self.steMoV()
activityView.center = CGPoint(x: self.view.center.x, y: self.view.center.y - kSafeArea_Top - 44)
//
activityView.hidesWhenStopped = true
activityView.color = .black;
activityView.style = UIActivityIndicatorView.Style.whiteLarge
self.view.addSubview(activityView)
self.view.bringSubviewToFront(tipLabel)
self.view.bringSubviewToFront(bgView)
self.bgView.isHidden = true
self.tipLabel.isHidden = true
// self.btn.isHidden = true
// self.activityView.startAnimating()
self.view.makeToast("Picture loading Please wait", duration: 1.5, position: .center)
// UIView
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(viewTapped))
livePhotoView.isUserInteractionEnabled = true
livePhotoView.addGestureRecognizer(tapGesture)
let model1 = WA_3DModel()
model1.preview = self.model.preview
model1.title = self.model.title
model1.thumbnail = self.model.thumbnail
model1.is_free = self.model.is_free
model1.category = self.model.category
model1.id = self.model.id
model1.cnt_like = self.model.cnt_like
liveManager.shared.addHistoryItem(item: model1)
}
@objc func buttonTapped(){
if self.isadshow == true{
if ATAdManager.shared().interstitialReady(forPlacementID: "n66bdc18696105"){
ATAdManager.shared().showInterstitial(withPlacementID: "n66bdc18696105", in: self, delegate: self)
StartManager.shared.shelfNumber = "动态详情页面show"
setPostSHOW()
self.navigationController?.popViewController(animated: true)
}else{
self.navigationController?.popViewController(animated: true)
}
}else{
self.navigationController?.popViewController(animated: true)
}
}
@objc func Retrybtntapped(){
// self.activityView.startAnimating()
self.animationView?.isHidden = false
self.Retrybtn.isHidden = true
steMoV()
}
//
@objc func viewTapped() {
// UIView
if bgView.frame.origin.y == UIScreen.main.bounds.height - bgView.frame.height {
// UIView
UIView.animate(withDuration: 0.5, animations: {
self.bgView.frame.origin.y += self.bgView.frame.height
self.tipLabel.frame.origin.y += self.bgView.frame.height - 20
self.bgView.alpha = 0
self.btn.isHidden = true
})
} else {
self.btn.isHidden = false
// UIView
UIView.animate(withDuration: 0.5, animations: {
self.bgView.frame.origin.y -= self.bgView.frame.height
self.tipLabel.frame.origin.y -= self.bgView.frame.height - 20
self.bgView.alpha = 1
})
}
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
self.navigationController?.navigationBar.isHidden = true
let size = self.view.bounds.size
self.sizi = size
// Remote Config
remoteConfig = RemoteConfig.remoteConfig()
//
let settings = RemoteConfigSettings()
settings.minimumFetchInterval = 0
remoteConfig.configSettings = settings
// Fetch
remoteConfig.setDefaults(fromPlist: "isopen")
loadTopAD()
}
func loadTopAD(){
let extra: [String: Any] = [
kATAdLoadingExtraMediaExtraKey: "custom_values"
]
ATAdManager.shared().loadAD(withPlacementID: "n66bdc18696105", extra: extra, delegate: self)
self.fetchRemoteConfig()
}
///广
func fetchRemoteConfig() {
let localVersion = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String ?? "0.0"
remoteConfig.fetch{ (status, error) -> Void in
if status == .success {
print("Config fetched!")
self.remoteConfig.activate { changed, error in
if error == nil{
let js = self.remoteConfig.configValue(forKey: "isopen").jsonValue as! [String:Any]
let valueopen = js["isadopen"] as! Bool
let valueversion = js["version"] as! String
DispatchQueue.main.async {
if valueversion == localVersion{
self.isadshow = false
}else{
if valueopen {
self.isadshow = true
} else {
self.isadshow = false
}
}
}
}
}
} else {
print("Config not fetched")
if let error = error {
print("Error: \(error.localizedDescription)")
}
}
}
}
@IBAction func saveBtn(_ sender: UIButton) {
self.exportLivePhoto()
self.activityView.startAnimating()
DispatchQueue.global().asyncAfter(deadline: .now() + 1.5) {
DispatchQueue.main.asyncAfter(deadline: .now() + 0){
self.activityView.stopAnimating()
// self.view.makeToast("Save Success", duration: 1.5, position: .center)
// UIAlertController
let alertController = UIAlertController(title: "Successfully saved", message: "Do you need to set up a tutorial", preferredStyle: .alert)
//
alertController.addAction(UIAlertAction(title: "cancel", style: .cancel, handler: nil))
//
alertController.addAction(UIAlertAction(title: "Need", style: .default, handler: { action in
//
// print("")
let vc = WA_TipVC()
self.present(vc, animated: true)
}))
// present
self.present(alertController, animated: true, completion: nil)
}
}
}
@IBAction func shareBtn(_ sender: UIButton) {
self.activityView.startAnimating()
//
guard let image = self.livePhotoView.livePhoto else {
SVProgressHUD.showInfo(withStatus: "Can't find the image to share")
DispatchQueue.global().asyncAfter(deadline: .now() + 2.0) {
SVProgressHUD.dismiss()
}
print("找不到要分享的图片")
return
}
//
let items: [Any] = [image]
// UIActivityViewController
let activityViewController = UIActivityViewController(activityItems: items, applicationActivities: nil)
// UIActivityViewController
activityViewController.modalPresentationStyle = .popover
// iPad UIActivityViewController
if let popoverController = activityViewController.popoverPresentationController {
popoverController.sourceView = self.view
popoverController.sourceRect = CGRect(x: self.view.bounds.midX, y: self.view.bounds.midY, width: 0, height: 0)
popoverController.permittedArrowDirections = []
}
//
self.present(activityViewController, animated: true, completion: nil)
DispatchQueue.main.asyncAfter(deadline: .now() + 0){
self.activityView.stopAnimating()
}
}
//mp4
func steMoV(){
// mp4 URL
let mp4URL = URL(string: "\(model.preview ?? "")")!
//
let documentsDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
let str = generateRandomString(length: 10)
let destinationURL = documentsDirectory.appendingPathComponent("\(str).mov")
//
let task = URLSession.shared.downloadTask(with: mp4URL) { (tempURL, response, error) in
guard let tempURL = tempURL else {
print("下载失败:\(error?.localizedDescription ?? "未知错误")")
DispatchQueue.main.asyncAfter(deadline: .now() + 0){
self.animationView?.isHidden = true
self.Retrybtn.isHidden = false
SVProgressHUD.showInfo(withStatus: "request timeout")
DispatchQueue.global().asyncAfter(deadline: .now() + 2.0) {
SVProgressHUD.dismiss()
}
}
return
}
do {
//
try FileManager.default.moveItem(at: tempURL, to: destinationURL)
//
print("下载完成:\(destinationURL)")
print("文档目录路径:\(documentsDirectory.path)")
self.animationView!.currentProgress = 0.5
// mp4 mov
self.convertMP4ToMOV(mp4URL: destinationURL)
} catch {
print("文件移动失败:\(error.localizedDescription)")
DispatchQueue.main.asyncAfter(deadline: .now() + 0){
self.animationView?.isHidden = true
self.Retrybtn.isHidden = false
SVProgressHUD.showInfo(withStatus: "request timeout")
DispatchQueue.global().asyncAfter(deadline: .now() + 2.0) {
SVProgressHUD.dismiss()
}
}
}
}
//
task.resume()
}
//mp4movjpg
func convertMP4ToMOV(mp4URL: URL) {
let asset = AVAsset(url: mp4URL)
let exportSession = AVAssetExportSession(asset: asset, presetName: AVAssetExportPresetHighestQuality)
//
let randomString = generateRandomString(length: 10)
//
guard let outputURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first?.appendingPathComponent("\(randomString).mov") else {
print("无法创建输出文件路径")
DispatchQueue.main.asyncAfter(deadline: .now() + 0){
self.animationView?.isHidden = true
self.Retrybtn.isHidden = false
SVProgressHUD.showInfo(withStatus: "request timeout")
DispatchQueue.global().asyncAfter(deadline: .now() + 2.0) {
SVProgressHUD.dismiss()
}
}
return
}
exportSession?.outputURL = outputURL
exportSession?.outputFileType = .mov
exportSession?.exportAsynchronously(completionHandler: {
DispatchQueue.main.async {
if exportSession?.status == .completed {
// URL
print("转换完成,保存位置:\(outputURL)")
self.animationView!.currentProgress = 0.8
self.loadVideoWithVideoURL(outputURL)
} else if exportSession?.status == .failed {
//
print("转换失败:\(exportSession?.error?.localizedDescription ?? "未知错误")")
DispatchQueue.main.asyncAfter(deadline: .now() + 0){
self.animationView?.isHidden = true
self.Retrybtn.isHidden = false
SVProgressHUD.showInfo(withStatus: "request timeout")
DispatchQueue.global().asyncAfter(deadline: .now() + 2.0) {
SVProgressHUD.dismiss()
}
}
}
}
})
}
func loadVideoWithVideoURL(_ videoURL: URL) {
// self.view.makeToast("Start", duration: 0.5, position: .center)
livePhotoView.livePhoto = nil
//URL
let asset = AVURLAsset(url: videoURL)
//
let generator = AVAssetImageGenerator(asset: asset)
//
generator.appliesPreferredTrackTransform = true
//
let time = NSValue(time: CMTimeMakeWithSeconds(CMTimeGetSeconds(asset.duration)/2, preferredTimescale: asset.duration.timescale))
//
generator.generateCGImagesAsynchronously(forTimes: [time]) { [weak self] _, image, _, _, _ in
if let image = image, let data = UIImage(cgImage: image).pngData() {
let urls = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
// selfURL
let imageURL = urls[0].appendingPathComponent("image.jpg")
//
try? data.write(to: imageURL, options: [.atomic])
let image = imageURL.path
let mov = videoURL.path
let output = FilePaths.VidToLive.livePath
// UUID
let assetIdentifier = UUID().uuidString
//
let _ = try? FileManager.default.createDirectory(atPath: output, withIntermediateDirectories: true, attributes: nil)
do {
//
try FileManager.default.removeItem(atPath: output + "/IMG.JPG")
try FileManager.default.removeItem(atPath: output + "/IMG.MOV")
} catch {
}
JPEG(path: image).write(output + "/IMG.JPG",
assetIdentifier: assetIdentifier)
QuickTimeMov(path: mov).write(output + "/IMG.MOV",
assetIdentifier: assetIdentifier)
if let sizi = self?.sizi {
_ = DispatchQueue.main.sync {
PHLivePhoto.request(withResourceFileURLs: [ URL(fileURLWithPath: FilePaths.VidToLive.livePath + "/IMG.MOV"), URL(fileURLWithPath: FilePaths.VidToLive.livePath + "/IMG.JPG")],
placeholderImage: nil,
targetSize: (self?.sizi)!,
contentMode: PHImageContentMode.aspectFit,
resultHandler:{ (livePhoto, info) -> Void in
self?.livePhotoView.livePhoto = livePhoto
if (info.first?.key.description == "PHLivePhotoInfoIsDegradedKey") && (info.first?.value as? NSInteger == 1) {
self?.animationView!.currentProgress = 1.0
self?.animationView?.isHidden = true
self?.bgView.isHidden = false
self?.tipLabel.isHidden = false
self?.btn.isHidden = false
}
})
}
} else {
// sizi nil
}
}
}
}
func exportLivePhoto () {
PHPhotoLibrary.shared().performChanges({ () -> Void in
// 使
let creationRequest = PHAssetCreationRequest.forAsset()
let options = PHAssetResourceCreationOptions()
// 使URL
creationRequest.addResource(with: PHAssetResourceType.pairedVideo, fileURL: URL(fileURLWithPath: FilePaths.VidToLive.livePath + "/IMG.MOV"), options: options)
creationRequest.addResource(with: PHAssetResourceType.photo, fileURL: URL(fileURLWithPath: FilePaths.VidToLive.livePath + "/IMG.JPG"), options: options)
}, completionHandler: { (success, error) -> Void in
if !success {
// DTLog((error?.localizedDescription)!)
print("转化错误: \(error?.localizedDescription ?? "")")
DispatchQueue.main.asyncAfter(deadline: .now() + 0){
self.animationView?.isHidden = true
self.Retrybtn.isHidden = false
SVProgressHUD.showInfo(withStatus: "request timeout")
DispatchQueue.global().asyncAfter(deadline: .now() + 2.0) {
SVProgressHUD.dismiss()
}
}
}
})
}
}
extension WA_LiveVideoVC:ATInterstitialDelegate{
// 广
func interstitialDidShow(forPlacementID placementID: String, extra: [AnyHashable : Any]) {
print("----成功")
}
/// 广
func interstitialDidClick(forPlacementID placementID: String, extra: [AnyHashable : Any]) {
print("----点击")
}
// 广
func interstitialDidClose(forPlacementID placementID: String, extra: [AnyHashable : Any]) {
print("----关闭")
// WA_TabbarCommon.TabBarController()
self.navigationController?.popViewController(animated: true)
}
func didFinishLoadingAD(withPlacementID placementID: String!) {
print("ATInterstitialViewController::didFailToLoadADWithPlacementID:\(placementID)")
}
// load
func didFailToLoadAD(withPlacementID placementID: String!, error: (any Error)!) {
print("----load失败")
print("ATInterstitialViewController::didFailToLoadADWithPlacementID:\(String(describing: placementID))---error\(String(describing: error))")
}
// 广
func didFinishLoadingADSource(withPlacementID placementID: String!,extra: [AnyHashable : Any]?) {
let networkID = extra?["network_firm_id"]
let ecpm = extra?["adsource_price"]
let country = extra?["country"]
if let adsourcePriceString = extra?["adsource_price"] as? String,
let adsourcePrice = Double(adsourcePriceString) {
StartManager.shared.ecpm = Float(adsourcePrice) / 1000
print("-----ecpm ID: \(StartManager.shared.ecpm)")
} else {
print("无法获取 adsource_price 或类型不匹配")
}
StartManager.shared.countryCode = country as? String
StartManager.shared.network = network(networkID as! Int)
StartManager.shared.shelfNumber = "动态详情页面load"
StartManager.shared.adId = "n66bdc18696105"
setPostload()
print("ATInterstitialViewController::didFailToLoadADWithPlacementID:\(placementID)")
}
}