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;
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;
+//////
+////// 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)
+// }
+//}
if toolBar.recordBtn.isSelected {
DcStereo.shared.recordStop()
}
+ pipManager.dissmiss()
super.navleftViewTapped()
}
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
}
else{
- pipManager.contentVC.updateRaw("蓝牙已断开".l10n)
- pipManager.contentVC.updateTrans("蓝牙已断开".l10n)
+ pipManager.updateRaw("蓝牙已断开".l10n)
+ pipManager.updateTrans("蓝牙已断开".l10n)
if toolBar.recordBtn.isSelected {
toolBar.recordBtnAction()
}
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)
}
}
+@available(iOS 15.0, *)
+extension PbSubTitleVC:PipManagerDelegate{
+ func pipStopAction(_ pip: PipManager) {
+ toolBar.recordBtnAction()
+ }
+}
@available(iOS 15.0, *)
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()
}
}
}
+////
+//// 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)
+// }
+// }
+//}
--- /dev/null
+//
+// 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
+ }
+ }
+
+}
let imgPicker = ImagePickerManager()
var languageChanged:(()->Void)?
var soureChanged:(()->Void)?
+ var showTypeChanged:(()->Void)?
+ var fontChanged:(()->Void)?
override func viewDidLoad() {
super.viewDidLoad()
cache.showType = list.first(where: {$0.title == value})!
SubTitleCache.shared.save(cache)
tableView.reloadData()
+ showTypeChanged?()
}
}
@objc func fontAction(){
cache.fontType = list.first(where: {$0.title == value})!
SubTitleCache.shared.save(cache)
tableView.reloadData()
+ fontChanged?()
}
}
}