From: liangzhenying <867174124@qq.com> Date: Fri, 3 Apr 2026 09:51:47 +0000 (+0800) Subject: 字幕修改 X-Git-Url: http://git.snicker.com.cn/sitemap.xml?a=commitdiff_plain;h=6979a693fc78609d478f6cddac882b65c12cfc72;p=mirrors%2FShenYin.git 字幕修改 --- diff --git a/ShenYin/ShenYin.xcodeproj/project.pbxproj b/ShenYin/ShenYin.xcodeproj/project.pbxproj index d7ed4ff..b5e5a20 100644 --- a/ShenYin/ShenYin.xcodeproj/project.pbxproj +++ b/ShenYin/ShenYin.xcodeproj/project.pbxproj @@ -1103,7 +1103,7 @@ CODE_SIGN_ENTITLEMENTS = ShenYin/Channel/DeepChords/DeepChords.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 202604011815; + CURRENT_PROJECT_VERSION = 202604031815; DEVELOPMENT_TEAM = MAC46RQ4KH; ENABLE_APP_SANDBOX = YES; ENABLE_HARDENED_RUNTIME = YES; @@ -1169,7 +1169,7 @@ CODE_SIGN_ENTITLEMENTS = ShenYin/Channel/DeepChords/DeepChords.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 202604011815; + CURRENT_PROJECT_VERSION = 202604031815; DEVELOPMENT_TEAM = MAC46RQ4KH; ENABLE_APP_SANDBOX = YES; ENABLE_HARDENED_RUNTIME = YES; diff --git a/ShenYin/ShenYin/Channel/DeepChords/Channel/UI/JoySubTitleVC.swift b/ShenYin/ShenYin/Channel/DeepChords/Channel/UI/JoySubTitleVC.swift index 4e33021..f5a698a 100644 --- a/ShenYin/ShenYin/Channel/DeepChords/Channel/UI/JoySubTitleVC.swift +++ b/ShenYin/ShenYin/Channel/DeepChords/Channel/UI/JoySubTitleVC.swift @@ -1,194 +1,196 @@ +////// +////// Untitled.swift +////// ShenYin +////// +////// Created by liangshi on 2026/3/5. +////// //// -//// Untitled.swift -//// ShenYin -//// -//// Created by liangshi on 2026/3/5. //// +//import UIKit +//import AVKit +//import JoyGemAI +//@available(iOS 15.0, *) +//class JoySubTitleVC: BaseVC { +// let languageItem = LanguageSelectItem() +// let toolBar = RecordBar() +// let pipManager = PipManager() +// var messageList : [(String,UInt)] = [] +// var translateList : [(String,UInt)] = [] +// +// override func viewDidLoad() { +// super.viewDidLoad() +// } +// override func viewDidAppear(_ animated: Bool) { +// super.viewDidAppear(animated) +// +// } +// override func viewWillAppear(_ animated: Bool) { +// super.viewWillAppear(animated) +// let cache = SubTitleCache.shared.get() +// languageItem.leftLabel.language = cache.lan_form +// languageItem.rightLabel.language = cache.lan_to +// } +// override func setupViews() { +// view.backgroundColor = UIColor.white +// navBar.do { v in +// v.backgroundColor = .white +// v.addSubview(languageItem) +// v.rightView.isHidden = false +// v.rightView.setImage(UIImage(named: "set_right"), for: .normal) +// } +// +// view.addSubviews([toolBar]) +// +// toolBar.do { v in +// v.delegate = self +// v.leftItem.isHidden = true +// v.rightItem.isHidden = true +// } +// languageItem.do { v in +// v.languageChange = { (from,to) in +// let cache = SubTitleCache.shared.get() +// cache.lan_form = from +// cache.lan_to = to +// SubTitleCache.shared.save(cache) +// } +// } +// pipManager.setup(superView: self.navigationController!.view) +// } +// override func setupLayout() { +// languageItem.snp.makeConstraints { make in +// make.left.right.equalToSuperview().inset(80) +// make.centerX.equalToSuperview() +// make.bottom.equalToSuperview().offset(5) +// } +// toolBar.snp.makeConstraints { make in +// make.width.centerX.equalToSuperview() +// make.height.equalTo(120) +// make.bottom.equalToSuperview() +// } +// } +// +// override func setupData() { +// do { +// try AVAudioSession.sharedInstance().setCategory(.playback) +// try AVAudioSession.sharedInstance().setActive(true) +// } catch { +// print(error) +// } +// JoyGemSubtitleManager.shared().delegate = self +// +// NotificationCenter.default.addObserver( +// self, +// selector: #selector(appDidEnterBackground(_:)), +// name: UIApplication.willResignActiveNotification, +// object: nil +// ) +// +// NotificationCenter.default.addObserver( +// self, +// selector: #selector(appWillEnterForeground(_:)), +// name: UIApplication.didBecomeActiveNotification, +// object: nil +// ) +// +// } +// override func navRightViewTapped() { +// let vc = SubTitleSetVC() +// App.shared.goToPage(vc) +// } +// +// +// @objc private func appDidEnterBackground(_ notification: Notification) { +//// pipManager.startPictureInPicture() +// } +// +// @objc private func appWillEnterForeground(_ notification: Notification) { +//// pipManager.stopPictureInPicture() +// } +//} +// +// // +//@available(iOS 15.0, *) +//extension JoySubTitleVC:RecordBarDelegate{ +// func recordBarLanguageChange(_ bar: RecordBar) { +// +// } +// func recordBar(_ bar: RecordBar, stateChange state: RecordBarSate) { +// if state == .start { +// JoyGemSubtitleManager.shared().originalLanguage = languageItem.leftLabel.language.value +// JoyGemSubtitleManager.shared().targetLanguage = languageItem.rightLabel.language.value +// JoyGemSubtitleManager.shared().start() +// pipManager.start() +// } +// else if state == .stop{ +// JoyGemSubtitleManager.shared().stop() +// pipManager.stop() +// } +// } +//} // -import UIKit -import AVKit -import JoyGemAI -@available(iOS 15.0, *) -class JoySubTitleVC: BaseVC { - let languageItem = LanguageSelectItem() - let toolBar = RecordBar() - let pipManager = PipManager() - var messageList : [(String,UInt)] = [] - var translateList : [(String,UInt)] = [] - - override func viewDidLoad() { - super.viewDidLoad() - } - override func viewDidAppear(_ animated: Bool) { - super.viewDidAppear(animated) - - } - override func viewWillAppear(_ animated: Bool) { - super.viewWillAppear(animated) - let cache = SubTitleCache.shared.get() - languageItem.leftLabel.language = cache.lan_form - languageItem.rightLabel.language = cache.lan_to - } - override func setupViews() { - view.backgroundColor = UIColor.white - navBar.do { v in - v.backgroundColor = .white - v.addSubview(languageItem) - v.rightView.isHidden = false - v.rightView.setImage(UIImage(named: "set_right"), for: .normal) - } - - view.addSubviews([toolBar]) - - toolBar.do { v in - v.delegate = self - v.leftItem.isHidden = true - v.rightItem.isHidden = true - } - languageItem.do { v in - v.languageChange = { (from,to) in - let cache = SubTitleCache.shared.get() - cache.lan_form = from - cache.lan_to = to - SubTitleCache.shared.save(cache) - } - } - pipManager.setupPictureInPicture(soureceView: self.navigationController!.view) - } - override func setupLayout() { - languageItem.snp.makeConstraints { make in - make.left.right.equalToSuperview().inset(80) - make.centerX.equalToSuperview() - make.bottom.equalToSuperview().offset(5) - } - toolBar.snp.makeConstraints { make in - make.width.centerX.equalToSuperview() - make.height.equalTo(120) - make.bottom.equalToSuperview() - } - } - - override func setupData() { - do { - try AVAudioSession.sharedInstance().setCategory(.playback) - try AVAudioSession.sharedInstance().setActive(true) - } catch { - print(error) - } - JoyGemSubtitleManager.shared().delegate = self - - NotificationCenter.default.addObserver( - self, - selector: #selector(appDidEnterBackground(_:)), - name: UIApplication.willResignActiveNotification, - object: nil - ) - - NotificationCenter.default.addObserver( - self, - selector: #selector(appWillEnterForeground(_:)), - name: UIApplication.didBecomeActiveNotification, - object: nil - ) - - } - override func navRightViewTapped() { - let vc = SubTitleSetVC() - App.shared.goToPage(vc) - } - - - @objc private func appDidEnterBackground(_ notification: Notification) { - pipManager.startPictureInPicture() - } - - @objc private func appWillEnterForeground(_ notification: Notification) { - pipManager.stopPictureInPicture() - } -} - - - -@available(iOS 15.0, *) -extension JoySubTitleVC:RecordBarDelegate{ - func recordBarLanguageChange(_ bar: RecordBar) { - - } - func recordBar(_ bar: RecordBar, stateChange state: RecordBarSate) { - if state == .start { - JoyGemSubtitleManager.shared().originalLanguage = languageItem.leftLabel.language.value - JoyGemSubtitleManager.shared().targetLanguage = languageItem.rightLabel.language.value - JoyGemSubtitleManager.shared().start() - } - else if state == .stop{ - JoyGemSubtitleManager.shared().stop() - } - } -} - -@available(iOS 15.0, *) -extension JoySubTitleVC : JoyGemSubtitleManagerDelegate { - - func subtitleManager(_ manager: JoyGemSubtitleManager, didUpdateRaw model: JoyGemAsrModel) { - debugPrint("text: \(model.text),index: \(model.index)") - updateRaw(model.text,model.index) - } - - func subtitleManager(_ manager: JoyGemSubtitleManager, didUpdateTranslate model: JoyGemAsrModel) { - debugPrint("translate text: \(model.text),index: \(model.index)") - updateTrans(model.text,model.index) - } - - func subtitleManagerStopped(_ manager: JoyGemSubtitleManager) { - - } - - func subtitleManager(_ manager: JoyGemSubtitleManager, stateChange code: JoyGemStateCode) { - - } - - func subtitleManager(_ manager: JoyGemSubtitleManager, onError code: JoyGemErrorCode) { - - } - - func subTitleManager(_ manager: JoyGemSubtitleManager, stateChange code: JoyGemStateCode) { - debugPrint("code: \(code)") - } - - func subTitleManager(_ manager: JoyGemSubtitleManager, onError code: JoyGemErrorCode) { - - } - - func updateRaw(_ text: String,_ index: UInt) { - let msg = messageList.firstIndex (where: { (str,idx) in - return idx == index; - }) - if (msg == nil) { - messageList.append((text,index)) - } else { - messageList[msg!] = (text,index) - } - - let res = messageList.compactMap({ (str,idx) in - return str - }).joined(separator: "\n") - pipManager.contentVC.updateRaw(res) - } - - func updateTrans(_ text: String,_ index: UInt) { - let msg = translateList.firstIndex (where: { (str,idx) in - return idx == index; - }) - if (msg == nil) { - translateList.append((text,index)) - } else { - translateList[msg!] = (text,index) - } - - let res = translateList.compactMap({ (str,idx) in - return str - }).joined(separator: "\n") - pipManager.contentVC.updateTrans(res) - } -} +//@available(iOS 15.0, *) +//extension JoySubTitleVC : JoyGemSubtitleManagerDelegate { +// +// func subtitleManager(_ manager: JoyGemSubtitleManager, didUpdateRaw model: JoyGemAsrModel) { +// debugPrint("text: \(model.text),index: \(model.index)") +// updateRaw(model.text,model.index) +// } +// +// func subtitleManager(_ manager: JoyGemSubtitleManager, didUpdateTranslate model: JoyGemAsrModel) { +// debugPrint("translate text: \(model.text),index: \(model.index)") +// updateTrans(model.text,model.index) +// } +// +// func subtitleManagerStopped(_ manager: JoyGemSubtitleManager) { +// +// } +// +// func subtitleManager(_ manager: JoyGemSubtitleManager, stateChange code: JoyGemStateCode) { +// +// } +// +// func subtitleManager(_ manager: JoyGemSubtitleManager, onError code: JoyGemErrorCode) { +// +// } +// +// func subTitleManager(_ manager: JoyGemSubtitleManager, stateChange code: JoyGemStateCode) { +// debugPrint("code: \(code)") +// } +// +// func subTitleManager(_ manager: JoyGemSubtitleManager, onError code: JoyGemErrorCode) { +// +// } +// +// func updateRaw(_ text: String,_ index: UInt) { +// let msg = messageList.firstIndex (where: { (str,idx) in +// return idx == index; +// }) +// if (msg == nil) { +// messageList.append((text,index)) +// } else { +// messageList[msg!] = (text,index) +// } +// +// let res = messageList.compactMap({ (str,idx) in +// return str +// }).joined(separator: "\n") +//// pipManager.contentVC.updateRaw(res) +// } +// +// func updateTrans(_ text: String,_ index: UInt) { +// let msg = translateList.firstIndex (where: { (str,idx) in +// return idx == index; +// }) +// if (msg == nil) { +// translateList.append((text,index)) +// } else { +// translateList[msg!] = (text,index) +// } +// +// let res = translateList.compactMap({ (str,idx) in +// return str +// }).joined(separator: "\n") +//// pipManager.contentVC.updateTrans(res) +// } +//} diff --git a/ShenYin/ShenYin/Channel/PLAYBOY/Channel/UI/PbSubTitleVC.swift b/ShenYin/ShenYin/Channel/PLAYBOY/Channel/UI/PbSubTitleVC.swift index 92640b8..ea4c318 100644 --- a/ShenYin/ShenYin/Channel/PLAYBOY/Channel/UI/PbSubTitleVC.swift +++ b/ShenYin/ShenYin/Channel/PLAYBOY/Channel/UI/PbSubTitleVC.swift @@ -42,6 +42,7 @@ class PbSubTitleVC: BaseVC { if toolBar.recordBtn.isSelected { DcStereo.shared.recordStop() } + pipManager.dissmiss() super.navleftViewTapped() } @@ -78,14 +79,10 @@ class PbSubTitleVC: BaseVC { v.separatorStyle = .none v.register(SubTitleCell.self, forCellReuseIdentifier: SubTitleCell.reuseID) } -// let soureView = UIView() -// soureView.backgroundColor = .red -// view.addSubviews([soureView]) -// soureView.snp.makeConstraints { make in -// make.size.equalTo(10) -// make.center.equalToSuperview() -// } - pipManager.setupPictureInPicture(soureceView: self.navigationController!.view) + pipManager.do { v in + v.delegate = self + v.reset(supperView: self.navigationController!.view) + } } override func setupLayout() { languageItem.snp.makeConstraints { make in @@ -128,8 +125,8 @@ class PbSubTitleVC: BaseVC { } else{ - pipManager.contentVC.updateRaw("蓝牙已断开".l10n) - pipManager.contentVC.updateTrans("蓝牙已断开".l10n) + pipManager.updateRaw("蓝牙已断开".l10n) + pipManager.updateTrans("蓝牙已断开".l10n) if toolBar.recordBtn.isSelected { toolBar.recordBtnAction() } @@ -148,24 +145,32 @@ class PbSubTitleVC: BaseVC { guard let self = self else{return} restart() } + vc.showTypeChanged = {[weak self] in + guard let self = self else{return} + pipManager.reset(supperView: self.navigationController!.view) + } + vc.fontChanged = {[weak self] in + guard let self = self else{return} + pipManager.reset(supperView: self.navigationController!.view) + } App.shared.goToPage(vc) } @objc private func appDidEnterBackground(_ notification: Notification) { if sdk.recording { - pipManager.startPictureInPicture() +// pipManager.startPictureInPicture() } } @objc private func appWillEnterForeground(_ notification: Notification) { - pipManager.stopPictureInPicture() +// pipManager.stopPictureInPicture() } func setupSdk(){ sdk.recordNeedReloadData = {[weak self] in guard let self = self else{return} if let model = sdk.dataList.last{ - pipManager.contentVC.updateRaw(model.send) - pipManager.contentVC.updateTrans(model.response) + pipManager.updateRaw(model.send) + pipManager.updateTrans(model.response) tableView.reloadData() if sdk.dataList.count > 0 { tableView.scrollToRow(at: IndexPath(row: sdk.dataList.count - 1, section: 0), at: .bottom, animated: true) @@ -183,6 +188,12 @@ class PbSubTitleVC: BaseVC { } } +@available(iOS 15.0, *) +extension PbSubTitleVC:PipManagerDelegate{ + func pipStopAction(_ pip: PipManager) { + toolBar.recordBtnAction() + } +} @available(iOS 15.0, *) extension PbSubTitleVC:RecordBarDelegate{ @@ -193,9 +204,11 @@ extension PbSubTitleVC:RecordBarDelegate{ func recordBar(_ bar: RecordBar, stateChange state: RecordBarSate) { if state == .start { sdk.startEarRecord(from: languageItem.leftLabel.language, to: languageItem.rightLabel.language) + pipManager.start() } else if state == .stop{ sdk.stopEarRecord() + pipManager.stop() } } } diff --git a/ShenYin/ShenYin/UI/Home/SubTitle/PipContentVC.swift b/ShenYin/ShenYin/UI/Home/SubTitle/PipContentVC.swift index 410fedc..f5313ed 100644 --- a/ShenYin/ShenYin/UI/Home/SubTitle/PipContentVC.swift +++ b/ShenYin/ShenYin/UI/Home/SubTitle/PipContentVC.swift @@ -1,198 +1,198 @@ +//// +//// Untitled.swift +//// ShenYin +//// +//// Created by liangshi on 2026/3/5. +//// // -// Untitled.swift -// ShenYin +//import AVKit +//import UIKit // -// Created by liangshi on 2026/3/5. +//@available(iOS 15.0, *) +//class PipManager:NSObject,AVPictureInPictureControllerDelegate{ +// var pipController: AVPictureInPictureController? +// var contentVC: PipContentVC! +// +// +// func setupPictureInPicture(soureceView:UIView) { +// guard AVPictureInPictureController.isPictureInPictureSupported() else { +// print("❌ 设备不支持画中画") +// return +// } +// +// contentVC = PipContentVC() +// let cache = SubTitleCache.shared.get() +// if cache.showType == .all { +// contentVC.preferredContentSize = CGSizeMake(kScreenWid, 100) +// } +// else{ +// contentVC.preferredContentSize = CGSizeMake(kScreenWid, 50) +// } +// let contentSource = AVPictureInPictureController.ContentSource( +// activeVideoCallSourceView:soureceView , +// contentViewController: contentVC +// ) +// +// pipController = AVPictureInPictureController(contentSource: contentSource) +// pipController?.delegate = self +//// pipController?.canStartPictureInPictureAutomaticallyFromInline = false +// } +// +// @objc func startPictureInPicture(){ +// guard let pipController = pipController else { +// Logger.debug("❌ pipController 未初始化,无法启动画中画") +// return +// } +// +// if pipController.isPictureInPicturePossible { +// Logger.debug("✅ 画中画可以启动,准备开始...") +// pipController.startPictureInPicture() +// contentVC?.reset() +// } else { +// Logger.debug("❌ 画中画当前无法启动") +// } +// } +// @objc func stopPictureInPicture() { +// guard let pipController = pipController else { +// Logger.debug("❌ pipController 未初始化,无法停止画中画") +// return +// } +// +// if pipController.isPictureInPictureActive { +// Logger.debug("✅ 画中画正在显示,准备停止...") +// pipController.stopPictureInPicture() +// Logger.debug("✅ 画中画已停止") +// } else { +// Logger.debug("⚠️ 画中画当前未显示") +// } +// } // - -import AVKit -import UIKit - -@available(iOS 15.0, *) -class PipManager:NSObject,AVPictureInPictureControllerDelegate{ - var pipController: AVPictureInPictureController? - var contentVC: PipContentVC! - - - func setupPictureInPicture(soureceView:UIView) { - guard AVPictureInPictureController.isPictureInPictureSupported() else { - print("❌ 设备不支持画中画") - return - } - - contentVC = PipContentVC() - let cache = SubTitleCache.shared.get() - if cache.showType == .all { - contentVC.preferredContentSize = CGSizeMake(kScreenWid, 100) - } - else{ - contentVC.preferredContentSize = CGSizeMake(kScreenWid, 50) - } - let contentSource = AVPictureInPictureController.ContentSource( - activeVideoCallSourceView:soureceView , - contentViewController: contentVC - ) - - pipController = AVPictureInPictureController(contentSource: contentSource) - pipController?.delegate = self -// pipController?.canStartPictureInPictureAutomaticallyFromInline = false - } - - @objc func startPictureInPicture(){ - guard let pipController = pipController else { - Logger.debug("❌ pipController 未初始化,无法启动画中画") - return - } - - if pipController.isPictureInPicturePossible { - Logger.debug("✅ 画中画可以启动,准备开始...") - pipController.startPictureInPicture() - contentVC?.reset() - } else { - Logger.debug("❌ 画中画当前无法启动") - } - } - @objc func stopPictureInPicture() { - guard let pipController = pipController else { - Logger.debug("❌ pipController 未初始化,无法停止画中画") - return - } - - if pipController.isPictureInPictureActive { - Logger.debug("✅ 画中画正在显示,准备停止...") - pipController.stopPictureInPicture() - Logger.debug("✅ 画中画已停止") - } else { - Logger.debug("⚠️ 画中画当前未显示") - } - } - - func pictureInPictureControllerWillStartPictureInPicture(_ pictureInPictureController: AVPictureInPictureController) { - Logger.debug("画中画即将开始") - } - - func pictureInPictureControllerDidStartPictureInPicture(_ pictureInPictureController: AVPictureInPictureController) { - Logger.debug("✅ 画中画已开始") - } - - func pictureInPictureController(_ pictureInPictureController: AVPictureInPictureController, failedToStartPictureInPictureWithError error: Error) { - Logger.debug("❌ 画中画启动失败: \(error)") - } - - func pictureInPictureControllerWillStopPictureInPicture(_ pictureInPictureController: AVPictureInPictureController) { - Logger.debug("⏹️ 画中画即将结束") - } - - func pictureInPictureControllerDidStopPictureInPicture(_ pictureInPictureController: AVPictureInPictureController) { - Logger.debug("🛑 画中画已结束") - } -} - - - -// 画中画内容视图控制器 -@available(iOS 15.0, *) -class PipContentVC : AVPictureInPictureVideoCallViewController { - var textView = UILabel() - var translateTextView = UILabel() - var line = UIView() - - override func viewDidLoad() { - super.viewDidLoad() - view.addSubviews([textView,translateTextView,line]) - view.backgroundColor = .black - reset() - } - - func updateRaw(_ text: String) { - textView.text = text -// textView.scrollRangeToVisible(NSRange(location: textView.text.count, length: 0)) - } - - func updateTrans(_ text : String) { - translateTextView.text = text -// translateTextView.scrollRangeToVisible(NSRange(location: translateTextView.text.count, length: 0)) - } - func reset(){ - -// setClearView() - - if (textView.superview == nil) { - return - } - let cache = SubTitleCache.shared.get() - if cache.showType == .all { - preferredContentSize = CGSizeMake(kScreenWid, 100) - } - else{ - preferredContentSize = CGSizeMake(kScreenWid, 50) - } - - textView.do { v in - v.textColor = .color(.level3) - v.font = cache.fontType.font - v.backgroundColor = .clear - v.adjustsFontSizeToFitWidth = true - v.numberOfLines = 0 - } - - translateTextView.do { v in - v.textColor = .white - v.font = cache.fontType.font - v.backgroundColor = .clear - v.adjustsFontSizeToFitWidth = true - v.numberOfLines = 0 - } - line.backgroundColor = .color(.separateLine).withAlphaComponent(0.5) - - - if cache.showType == .all { - textView.snp.remakeConstraints { make in - make.top.equalToSuperview().inset(10) - make.leading.trailing.equalToSuperview().inset(16) - make.bottom.equalTo(view.snp.centerY) - } - translateTextView.snp.remakeConstraints { make in - make.leading.trailing.equalToSuperview().inset(16) - make.top.equalTo(textView.snp.bottom).offset(2) - make.bottom.equalToSuperview().inset(10) - } - line.snp.remakeConstraints { make in - make.bottom.equalTo(textView.snp.bottom) - make.leading.trailing.equalToSuperview().inset(16) - make.height.equalTo(0.5) - } - textView.isHidden = false - translateTextView.isHidden = false - line.isHidden = false - } - else if cache.showType == .from { - textView.snp.remakeConstraints { make in - make.top.bottom.equalToSuperview().inset(10) - make.leading.trailing.equalToSuperview().inset(16) - } - textView.isHidden = false - translateTextView.isHidden = true - line.isHidden = true - } else { - translateTextView.snp.remakeConstraints { make in - make.top.bottom.equalToSuperview().inset(10) - make.leading.trailing.equalToSuperview().inset(16) - } - textView.isHidden = true - translateTextView.isHidden = false - line.isHidden = true - } - } - func setClearView(){ - for window in UIApplication.shared.windows { - finedView(window) - } - } - func finedView(_ sView:UIView){ - sView.backgroundColor = .clear - for v in sView.subviews { - finedView(v) - } - } -} +// func pictureInPictureControllerWillStartPictureInPicture(_ pictureInPictureController: AVPictureInPictureController) { +// Logger.debug("画中画即将开始") +// } +// +// func pictureInPictureControllerDidStartPictureInPicture(_ pictureInPictureController: AVPictureInPictureController) { +// Logger.debug("✅ 画中画已开始") +// } +// +// func pictureInPictureController(_ pictureInPictureController: AVPictureInPictureController, failedToStartPictureInPictureWithError error: Error) { +// Logger.debug("❌ 画中画启动失败: \(error)") +// } +// +// func pictureInPictureControllerWillStopPictureInPicture(_ pictureInPictureController: AVPictureInPictureController) { +// Logger.debug("⏹️ 画中画即将结束") +// } +// +// func pictureInPictureControllerDidStopPictureInPicture(_ pictureInPictureController: AVPictureInPictureController) { +// Logger.debug("🛑 画中画已结束") +// } +//} +// +// +// +//// 画中画内容视图控制器 +//@available(iOS 15.0, *) +//class PipContentVC : AVPictureInPictureVideoCallViewController { +// var textView = UILabel() +// var translateTextView = UILabel() +// var line = UIView() +// +// override func viewDidLoad() { +// super.viewDidLoad() +// view.addSubviews([textView,translateTextView,line]) +// view.backgroundColor = .black +// reset() +// } +// +// func updateRaw(_ text: String) { +// textView.text = text +//// textView.scrollRangeToVisible(NSRange(location: textView.text.count, length: 0)) +// } +// +// func updateTrans(_ text : String) { +// translateTextView.text = text +//// translateTextView.scrollRangeToVisible(NSRange(location: translateTextView.text.count, length: 0)) +// } +// func reset(){ +// +//// setClearView() +// +// if (textView.superview == nil) { +// return +// } +// let cache = SubTitleCache.shared.get() +// if cache.showType == .all { +// preferredContentSize = CGSizeMake(kScreenWid, 100) +// } +// else{ +// preferredContentSize = CGSizeMake(kScreenWid, 50) +// } +// +// textView.do { v in +// v.textColor = .color(.level3) +// v.font = cache.fontType.font +// v.backgroundColor = .clear +// v.adjustsFontSizeToFitWidth = true +// v.numberOfLines = 0 +// } +// +// translateTextView.do { v in +// v.textColor = .white +// v.font = cache.fontType.font +// v.backgroundColor = .clear +// v.adjustsFontSizeToFitWidth = true +// v.numberOfLines = 0 +// } +// line.backgroundColor = .color(.separateLine).withAlphaComponent(0.5) +// +// +// if cache.showType == .all { +// textView.snp.remakeConstraints { make in +// make.top.equalToSuperview().inset(10) +// make.leading.trailing.equalToSuperview().inset(16) +// make.bottom.equalTo(view.snp.centerY) +// } +// translateTextView.snp.remakeConstraints { make in +// make.leading.trailing.equalToSuperview().inset(16) +// make.top.equalTo(textView.snp.bottom).offset(2) +// make.bottom.equalToSuperview().inset(10) +// } +// line.snp.remakeConstraints { make in +// make.bottom.equalTo(textView.snp.bottom) +// make.leading.trailing.equalToSuperview().inset(16) +// make.height.equalTo(0.5) +// } +// textView.isHidden = false +// translateTextView.isHidden = false +// line.isHidden = false +// } +// else if cache.showType == .from { +// textView.snp.remakeConstraints { make in +// make.top.bottom.equalToSuperview().inset(10) +// make.leading.trailing.equalToSuperview().inset(16) +// } +// textView.isHidden = false +// translateTextView.isHidden = true +// line.isHidden = true +// } else { +// translateTextView.snp.remakeConstraints { make in +// make.top.bottom.equalToSuperview().inset(10) +// make.leading.trailing.equalToSuperview().inset(16) +// } +// textView.isHidden = true +// translateTextView.isHidden = false +// line.isHidden = true +// } +// } +// func setClearView(){ +// for window in UIApplication.shared.windows { +// finedView(window) +// } +// } +// func finedView(_ sView:UIView){ +// sView.backgroundColor = .clear +// for v in sView.subviews { +// finedView(v) +// } +// } +//} diff --git a/ShenYin/ShenYin/UI/Home/SubTitle/PipManager.swift b/ShenYin/ShenYin/UI/Home/SubTitle/PipManager.swift new file mode 100644 index 0000000..dd21d79 --- /dev/null +++ b/ShenYin/ShenYin/UI/Home/SubTitle/PipManager.swift @@ -0,0 +1,219 @@ +// +// PipManager.swift +// PipDemo +// +// Created by liangshi on 2026/4/2. +// + +import UIKit +import AVKit +import AVFoundation + +protocol PipManagerDelegate:NSObject { + func pipStopAction(_ pip:PipManager) +} + +class PipManager: NSObject { + private var pipController: AVPictureInPictureController? + private var contentView = PipContentView() + weak var delegate:PipManagerDelegate? + var playerLayer: AVPlayerLayer? + + func dissmiss(){ + if let pip = pipController{ + pip.stopPictureInPicture() + pipController = nil + playerLayer?.removeFromSuperlayer() + } + } + + func reset(supperView:UIView){ + var isStart = false + if let pip = pipController{ + isStart = pip.isPictureInPictureActive + pip.stopPictureInPicture() + pipController = nil + playerLayer?.removeFromSuperlayer() + } + + do { + try AVAudioSession.sharedInstance().setCategory(.playback, mode: .moviePlayback, options: [.allowAirPlay, .allowBluetooth]) + try AVAudioSession.sharedInstance().setActive(true) + } catch { + Logger.debug("Audio session setup failed: \(error)") + } + + + if SubTitleCache.shared.get().showType == .all { + playerLayer = AVPlayerLayer(player: AVPlayer(url: Bundle.main.url(forResource: "shu2", withExtension: "mp4")!)) + playerLayer?.frame = CGRect(x: 10, y: kScreenHei, width: kScreenWid - 20, height: 80) + contentView.frame = CGRectMake(0, 0, kScreenWid - 20, 80) + contentView.reset() + } + else{ + playerLayer = AVPlayerLayer(player: AVPlayer(url: Bundle.main.url(forResource: "shu1", withExtension: "mp4")!)) + playerLayer?.frame = CGRect(x: 10, y: kScreenHei, width: kScreenWid - 20, height: 40) + contentView.frame = CGRectMake(0, 0, kScreenWid - 20, 40) + contentView.reset() + } + + playerLayer?.videoGravity = .resizeAspect + playerLayer?.backgroundColor = UIColor.black.cgColor + playerLayer?.cornerRadius = 10 + playerLayer?.masksToBounds = true + supperView.layer.addSublayer(playerLayer!) + + pipController = AVPictureInPictureController(playerLayer: playerLayer!) + pipController?.delegate = self + pipController?.setValue(1, forKey: "controlsStyle") + + if isStart { + DispatchQueue.main.asyncAfter(deadline:.now() + 0.2) { + Logger.debug("延迟0.2秒后执行") + self.start() + } + } + } + + func start() { + guard let controller = pipController else { return } + if controller.isPictureInPicturePossible == true { + do { + try controller.startPictureInPicture() + Logger.debug("画中画启动成功") + } catch { + Logger.debug("画中画启动失败: \(error)") + } + } + } + + func stop() { + pipController?.stopPictureInPicture() + } + func updateRaw(_ text: String) { + contentView.textView.text = text + // textView.scrollRangeToVisible(NSRange(location: textView.text.count, length: 0)) + } + + func updateTrans(_ text : String) { + contentView.translateTextView.text = text + // translateTextView.scrollRangeToVisible(NSRange(location: translateTextView.text.count, length: 0)) + } +} + +extension PipManager: AVPictureInPictureControllerDelegate { + func pictureInPictureControllerWillStartPictureInPicture(_ pictureInPictureController: AVPictureInPictureController) { + Logger.debug("画中画即将开始") + UIApplication.shared.windows.first!.addSubview(self.contentView) +// playerLayer?.isHidden = true + } + + func pictureInPictureControllerDidStartPictureInPicture(_ pictureInPictureController: AVPictureInPictureController) { + Logger.debug("画中画已开始") + } + + func pictureInPictureControllerWillStopPictureInPicture(_ pictureInPictureController: AVPictureInPictureController) { + Logger.debug("画中画即将停止") +// self.contentView.removeFromSuperview() + } + + func pictureInPictureControllerDidStopPictureInPicture(_ pictureInPictureController: AVPictureInPictureController) { + Logger.debug("画中画已停止") + delegate?.pipStopAction(self) + } + + func pictureInPictureController(_ pictureInPictureController: AVPictureInPictureController, failedToStartPictureInPictureWithError error: Error) { + Logger.debug("画中画启动失败:\(error.localizedDescription)") + } + + func pictureInPictureController(_ pictureInPictureController: AVPictureInPictureController, restoreUserInterfaceForPictureInPictureStopWithCompletionHandler completionHandler: @escaping (Bool) -> Void) { + Logger.debug("用户点击了还原按钮") + completionHandler(false) + } +} + +class PipContentView : UIView { + var textView = UILabel() + var translateTextView = UILabel() + var line = UIView() + + override init(frame: CGRect) { + super.init(frame: frame) + addSubviews([textView,translateTextView,line]) + backgroundColor = .black + reset() + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + fileprivate func reset(){ + if (textView.superview == nil) { + return + } + let cache = SubTitleCache.shared.get() + textView.do { v in + v.textColor = .color(.level3) + v.font = cache.fontType.font + v.backgroundColor = .clear + v.adjustsFontSizeToFitWidth = true + v.numberOfLines = 0 + } + + translateTextView.do { v in + v.textColor = .white + v.font = cache.fontType.font + v.backgroundColor = .clear + v.adjustsFontSizeToFitWidth = true + v.numberOfLines = 0 + } + line.backgroundColor = .color(.separateLine).withAlphaComponent(0.5) + + + if cache.showType == .all { + textView.snp.remakeConstraints { make in + make.top.equalToSuperview().inset(10) + make.leading.trailing.equalToSuperview().inset(16) + make.bottom.equalTo(self.snp.centerY) + } + translateTextView.snp.remakeConstraints { make in + make.leading.trailing.equalToSuperview().inset(16) + make.top.equalTo(textView.snp.bottom).offset(2) + make.bottom.equalToSuperview().inset(10) + } + line.snp.remakeConstraints { make in + make.bottom.equalTo(textView.snp.bottom) + make.leading.trailing.equalToSuperview().inset(16) + make.height.equalTo(0.5) + } + textView.textColor = .color(.level3) + translateTextView.textColor = .white + textView.isHidden = false + translateTextView.isHidden = false + line.isHidden = false + } + else if cache.showType == .from { + textView.snp.remakeConstraints { make in + make.top.bottom.equalToSuperview().inset(10) + make.leading.trailing.equalToSuperview().inset(16) + } + textView.textColor = .white + translateTextView.textColor = .white + textView.isHidden = false + translateTextView.isHidden = true + line.isHidden = true + } else { + translateTextView.snp.remakeConstraints { make in + make.top.bottom.equalToSuperview().inset(10) + make.leading.trailing.equalToSuperview().inset(16) + } + textView.textColor = .white + translateTextView.textColor = .white + textView.isHidden = true + translateTextView.isHidden = false + line.isHidden = true + } + } + +} diff --git a/ShenYin/ShenYin/UI/Home/SubTitle/SubTitleSetVC.swift b/ShenYin/ShenYin/UI/Home/SubTitle/SubTitleSetVC.swift index 7c5c581..07dc0e5 100644 --- a/ShenYin/ShenYin/UI/Home/SubTitle/SubTitleSetVC.swift +++ b/ShenYin/ShenYin/UI/Home/SubTitle/SubTitleSetVC.swift @@ -12,6 +12,8 @@ class SubTitleSetVC: BaseVC{ let imgPicker = ImagePickerManager() var languageChanged:(()->Void)? var soureChanged:(()->Void)? + var showTypeChanged:(()->Void)? + var fontChanged:(()->Void)? override func viewDidLoad() { super.viewDidLoad() @@ -121,6 +123,7 @@ extension SubTitleSetVC{ cache.showType = list.first(where: {$0.title == value})! SubTitleCache.shared.save(cache) tableView.reloadData() + showTypeChanged?() } } @objc func fontAction(){ @@ -134,6 +137,7 @@ extension SubTitleSetVC{ cache.fontType = list.first(where: {$0.title == value})! SubTitleCache.shared.save(cache) tableView.reloadData() + fontChanged?() } } } diff --git a/ShenYin/ShenYin/UI/Home/SubTitle/shu1.mp4 b/ShenYin/ShenYin/UI/Home/SubTitle/shu1.mp4 new file mode 100644 index 0000000..452e9e8 Binary files /dev/null and b/ShenYin/ShenYin/UI/Home/SubTitle/shu1.mp4 differ diff --git a/ShenYin/ShenYin/UI/Home/SubTitle/shu2.mp4 b/ShenYin/ShenYin/UI/Home/SubTitle/shu2.mp4 new file mode 100644 index 0000000..bc65daa Binary files /dev/null and b/ShenYin/ShenYin/UI/Home/SubTitle/shu2.mp4 differ