加了画中画
authorliangzhenying <867174124@qq.com>
Fri, 6 Mar 2026 10:03:32 +0000 (18:03 +0800)
committerliangzhenying <867174124@qq.com>
Fri, 6 Mar 2026 10:03:32 +0000 (18:03 +0800)
17 files changed:
ShenYin/DeepChordsSdk/DCSdk.swift
ShenYin/ShenYin.xcodeproj/project.pbxproj
ShenYin/ShenYin.xcodeproj/xcshareddata/xcschemes/playboy.xcscheme [new file with mode: 0644]
ShenYin/ShenYin/Assets.xcassets/device/pip_close.imageset/Contents.json [new file with mode: 0644]
ShenYin/ShenYin/Assets.xcassets/device/pip_close.imageset/Slice 49@2x.png [new file with mode: 0644]
ShenYin/ShenYin/Assets.xcassets/device/pip_close.imageset/Slice 49@3x.png [new file with mode: 0644]
ShenYin/ShenYin/Assets.xcassets/device/pip_set.imageset/Contents.json [new file with mode: 0644]
ShenYin/ShenYin/Assets.xcassets/device/pip_set.imageset/Slice 47@2x.png [new file with mode: 0644]
ShenYin/ShenYin/Assets.xcassets/device/pip_set.imageset/Slice 47@3x.png [new file with mode: 0644]
ShenYin/ShenYin/Sdk/JoySdk/VC/HomeDeviceVC.swift
ShenYin/ShenYin/ShenYin copy-Info.plist
ShenYin/ShenYin/UI/Base/BaseTC.swift
ShenYin/ShenYin/UI/Home/SubTitle/LanguagePickerView1.swift [new file with mode: 0644]
ShenYin/ShenYin/UI/Home/SubTitle/PiPManager.swift [new file with mode: 0644]
ShenYin/ShenYin/UI/Home/SubTitle/PipPicker.swift [new file with mode: 0644]
ShenYin/ShenYin/UI/Home/SubTitle/PipSetView.swift [new file with mode: 0644]
ShenYin/ShenYin/UI/Home/SubTitle/SubTitleVC.swift [new file with mode: 0644]

index b6a2a7e..8238e97 100644 (file)
@@ -25,7 +25,7 @@ public class DCSdk{
 //        StarburstConfig.shared().sdkFolder = NSHomeDirectory() + "/Documents/DeepChordsSdk"
         // 日志路径
 //        StarburstConfig.shared().logPath = logFilePath()
-        StarburstConfig.shared().logPath = nil
+//        StarburstConfig.shared().logPath = nil
         //是否下发文字到耳机仓
         StarburstConfig.shared().enableTextSyncToDevice = false
         //主从耳机切换是否同步sdk信息到耳机
index a8d96c3..d74af2a 100644 (file)
@@ -17,8 +17,8 @@
                644D1BB5EDD3EA1D77C57786 /* Pods_DeepChordsSdk.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 248D8B53B5A178ACA5867275 /* Pods_DeepChordsSdk.framework */; };
                7666589AAA94A323B6090425 /* Pods_playboy.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A4F1BB919D567C3B6B0EBAA7 /* Pods_playboy.framework */; };
                7A6613B4B617D6E71D34944C /* Pods_ShenYin.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 90FF0C8B0D4D6AE0933FA672 /* Pods_ShenYin.framework */; };
-               817510A595D00CAD05E3772C /* BuildFile in Frameworks */ = {isa = PBXBuildFile; };
-               F2E449CAD5874BE652A69B50 /* BuildFile in Frameworks */ = {isa = PBXBuildFile; };
+               817510A595D00CAD05E3772C /* (null) in Frameworks */ = {isa = PBXBuildFile; };
+               F2E449CAD5874BE652A69B50 /* (null) in Frameworks */ = {isa = PBXBuildFile; };
 /* End PBXBuildFile section */
 
 /* Begin PBXContainerItemProxy section */
                                Sdk/JoySdk/VC/JoyTctyVC.swift,
                                Sdk/JoySdk/VC/JoyXclyVC.swift,
                                Sdk/JoySdk/VC/ModeVC.swift,
+                               UI/Home/SubTitle/LanguagePickerView1.swift,
+                               UI/Home/SubTitle/PiPManager.swift,
+                               UI/Home/SubTitle/PipPicker.swift,
+                               UI/Home/SubTitle/PipSetView.swift,
+                               UI/Home/SubTitle/SubTitleVC.swift,
                        );
                        target = 3FD1DFE32F0E00BF00A62733 /* playboy */;
                };
 /* End PBXFileSystemSynchronizedBuildFileExceptionSet section */
 
 /* Begin PBXFileSystemSynchronizedGroupBuildPhaseMembershipExceptionSet section */
-               3FCC8B152F1E0280004C2A13 /* Exceptions for "ShenYin" folder in "Embed Frameworks" build phase */ = {
+               3FCC8B152F1E0280004C2A13 /* Exceptions for "ShenYin" folder in "Embed Frameworks" phase from "ShenYin" target */ = {
                        isa = PBXFileSystemSynchronizedGroupBuildPhaseMembershipExceptionSet;
+                       attributesByRelativePath = {
+                               Sdk/JoySdk/tool/JoyGemAI.framework = (CodeSignOnCopy, RemoveHeadersOnCopy, );
+                       };
                        buildPhase = 3FEFE9092F1B252000D82F17 /* Embed Frameworks */;
                        membershipExceptions = (
                                Sdk/JoySdk/tool/JoyGemAI.framework,
                        );
                };
-               3FCC8B1A2F1E030E004C2A13 /* Exceptions for "ShenYin" folder in "Embed Frameworks" build phase */ = {
+               3FCC8B1A2F1E030E004C2A13 /* Exceptions for "ShenYin" folder in "Embed Frameworks" phase from "playboy" target */ = {
                        isa = PBXFileSystemSynchronizedGroupBuildPhaseMembershipExceptionSet;
+                       attributesByRelativePath = {
+                               Sdk/DcSdk/tool/JLAudioUnitKit.xcframework = (CodeSignOnCopy, RemoveHeadersOnCopy, );
+                       };
                        buildPhase = 3FD1DFEF2F0E00BF00A62733 /* Embed Frameworks */;
                        membershipExceptions = (
                                Sdk/DcSdk/tool/JLAudioUnitKit.xcframework,
                        );
                };
-               3FFB77C62F17A11100EF9A60 /* Exceptions for "DeepChordsSdk" folder in "Embed Frameworks" build phase */ = {
+               3FFB77C62F17A11100EF9A60 /* Exceptions for "DeepChordsSdk" folder in "Embed Frameworks" phase from "DeepChordsSdk" target */ = {
                        isa = PBXFileSystemSynchronizedGroupBuildPhaseMembershipExceptionSet;
+                       attributesByRelativePath = {
+                               StarburstSdk.framework = (CodeSignOnCopy, RemoveHeadersOnCopy, );
+                       };
                        buildPhase = 3FFB77C52F17A11100EF9A60 /* Embed Frameworks */;
                        membershipExceptions = (
                                StarburstSdk.framework,
                0D54E0F02F0A61E600A80EE7 /* DeepChordsSdk */ = {
                        isa = PBXFileSystemSynchronizedRootGroup;
                        exceptions = (
-                               3FFB77C62F17A11100EF9A60 /* Exceptions for "DeepChordsSdk" folder in "Embed Frameworks" build phase */,
+                               3FFB77C62F17A11100EF9A60 /* Exceptions for "DeepChordsSdk" folder in "Embed Frameworks" phase from "DeepChordsSdk" target */,
                                3FFB77C82F17A14C00EF9A60 /* Exceptions for "DeepChordsSdk" folder in "playboy" target */,
                        );
                        path = DeepChordsSdk;
                        isa = PBXFileSystemSynchronizedRootGroup;
                        exceptions = (
                                3F887BAE2E38D8DD00C98658 /* Exceptions for "ShenYin" folder in "ShenYin" target */,
-                               3FCC8B152F1E0280004C2A13 /* Exceptions for "ShenYin" folder in "Embed Frameworks" build phase */,
+                               3FCC8B152F1E0280004C2A13 /* Exceptions for "ShenYin" folder in "Embed Frameworks" phase from "ShenYin" target */,
                                3FD1DFF52F0E00BF00A62733 /* Exceptions for "ShenYin" folder in "playboy" target */,
-                               3FCC8B1A2F1E030E004C2A13 /* Exceptions for "ShenYin" folder in "Embed Frameworks" build phase */,
+                               3FCC8B1A2F1E030E004C2A13 /* Exceptions for "ShenYin" folder in "Embed Frameworks" phase from "playboy" target */,
                                3F03696C2F2B604900F3CB95 /* Exceptions for "ShenYin" folder in "playboy copy" target */,
                        );
                        path = ShenYin;
                        isa = PBXFrameworksBuildPhase;
                        buildActionMask = 2147483647;
                        files = (
-                               F2E449CAD5874BE652A69B50 /* BuildFile in Frameworks */,
+                               F2E449CAD5874BE652A69B50 /* (null) in Frameworks */,
                                7A6613B4B617D6E71D34944C /* Pods_ShenYin.framework in Frameworks */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                        buildActionMask = 2147483647;
                        files = (
                                3FFB77C12F179F3100EF9A60 /* DeepChordsSdk.framework in Frameworks */,
-                               817510A595D00CAD05E3772C /* BuildFile in Frameworks */,
+                               817510A595D00CAD05E3772C /* (null) in Frameworks */,
                                30B13DEF1AA0E4C54D873276 /* Pods_playboy.framework in Frameworks */,
                                7666589AAA94A323B6090425 /* Pods_playboy.framework in Frameworks */,
                        );
                        inputFileListPaths = (
                                "${PODS_ROOT}/Target Support Files/Pods-ShenYin/Pods-ShenYin-resources-${CONFIGURATION}-input-files.xcfilelist",
                        );
+                       inputPaths = (
+                       );
                        name = "[CP] Copy Pods Resources";
                        outputFileListPaths = (
                                "${PODS_ROOT}/Target Support Files/Pods-ShenYin/Pods-ShenYin-resources-${CONFIGURATION}-output-files.xcfilelist",
                        );
+                       outputPaths = (
+                       );
                        runOnlyForDeploymentPostprocessing = 0;
                        shellPath = /bin/sh;
                        shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-ShenYin/Pods-ShenYin-resources.sh\"\n";
                        inputFileListPaths = (
                                "${PODS_ROOT}/Target Support Files/Pods-playboy/Pods-playboy-frameworks-${CONFIGURATION}-input-files.xcfilelist",
                        );
+                       inputPaths = (
+                       );
                        name = "[CP] Embed Pods Frameworks";
                        outputFileListPaths = (
                                "${PODS_ROOT}/Target Support Files/Pods-playboy/Pods-playboy-frameworks-${CONFIGURATION}-output-files.xcfilelist",
                        );
+                       outputPaths = (
+                       );
                        runOnlyForDeploymentPostprocessing = 0;
                        shellPath = /bin/sh;
                        shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-playboy/Pods-playboy-frameworks.sh\"\n";
                        inputFileListPaths = (
                                "${PODS_ROOT}/Target Support Files/Pods-ShenYin/Pods-ShenYin-frameworks-${CONFIGURATION}-input-files.xcfilelist",
                        );
+                       inputPaths = (
+                       );
                        name = "[CP] Embed Pods Frameworks";
                        outputFileListPaths = (
                                "${PODS_ROOT}/Target Support Files/Pods-ShenYin/Pods-ShenYin-frameworks-${CONFIGURATION}-output-files.xcfilelist",
                        );
+                       outputPaths = (
+                       );
                        runOnlyForDeploymentPostprocessing = 0;
                        shellPath = /bin/sh;
                        shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-ShenYin/Pods-ShenYin-frameworks.sh\"\n";
                                CODE_SIGN_ENTITLEMENTS = ShenYin/PLAYBOY.entitlements;
                                CODE_SIGN_IDENTITY = "Apple Development";
                                CODE_SIGN_STYLE = Automatic;
-                               CURRENT_PROJECT_VERSION = 202603031106;
+                               CURRENT_PROJECT_VERSION = 202603051206;
                                DEVELOPMENT_TEAM = JKLJ58J33Q;
                                FRAMEWORK_SEARCH_PATHS = (
                                        "$(inherited)",
                                );
                                GENERATE_INFOPLIST_FILE = YES;
                                INFOPLIST_FILE = "ShenYin/ShenYin copy-Info.plist";
-                               INFOPLIST_KEY_CFBundleDisplayName = PLAYBOY;
+                               INFOPLIST_KEY_CFBundleDisplayName = "PLAYBOY眼镜";
                                INFOPLIST_KEY_ITSAppUsesNonExemptEncryption = NO;
                                INFOPLIST_KEY_NSBluetoothAlwaysUsageDescription = "扫描附近蓝牙设备需要获得权限";
                                INFOPLIST_KEY_NSCameraUsageDescription = "修改用户头像、提交意见反馈需要访问相册使用摄像头";
                                        "@executable_path/Frameworks",
                                );
                                LIBRARY_SEARCH_PATHS = "$(inherited)";
-                               MARKETING_VERSION = 1.0.0;
+                               MARKETING_VERSION = 0.01;
                                PRODUCT_BUNDLE_IDENTIFIER = com.ios.playboy;
                                PRODUCT_NAME = "$(TARGET_NAME)";
                                PROVISIONING_PROFILE_SPECIFIER = "";
                                CODE_SIGN_ENTITLEMENTS = ShenYin/PLAYBOY.entitlements;
                                CODE_SIGN_IDENTITY = "Apple Development";
                                CODE_SIGN_STYLE = Automatic;
-                               CURRENT_PROJECT_VERSION = 202603031106;
+                               CURRENT_PROJECT_VERSION = 202603051206;
                                DEVELOPMENT_TEAM = JKLJ58J33Q;
                                FRAMEWORK_SEARCH_PATHS = (
                                        "$(inherited)",
                                );
                                GENERATE_INFOPLIST_FILE = YES;
                                INFOPLIST_FILE = "ShenYin/ShenYin copy-Info.plist";
-                               INFOPLIST_KEY_CFBundleDisplayName = PLAYBOY;
+                               INFOPLIST_KEY_CFBundleDisplayName = "PLAYBOY眼镜";
                                INFOPLIST_KEY_ITSAppUsesNonExemptEncryption = NO;
                                INFOPLIST_KEY_NSBluetoothAlwaysUsageDescription = "扫描附近蓝牙设备需要获得权限";
                                INFOPLIST_KEY_NSCameraUsageDescription = "修改用户头像、提交意见反馈需要访问相册使用摄像头";
                                        "@executable_path/Frameworks",
                                );
                                LIBRARY_SEARCH_PATHS = "$(inherited)";
-                               MARKETING_VERSION = 1.0.0;
+                               MARKETING_VERSION = 0.01;
                                PRODUCT_BUNDLE_IDENTIFIER = com.ios.playboy;
                                PRODUCT_NAME = "$(TARGET_NAME)";
                                PROVISIONING_PROFILE_SPECIFIER = "";
diff --git a/ShenYin/ShenYin.xcodeproj/xcshareddata/xcschemes/playboy.xcscheme b/ShenYin/ShenYin.xcodeproj/xcshareddata/xcschemes/playboy.xcscheme
new file mode 100644 (file)
index 0000000..2cabc21
--- /dev/null
@@ -0,0 +1,78 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Scheme
+   LastUpgradeVersion = "2620"
+   version = "1.7">
+   <BuildAction
+      parallelizeBuildables = "YES"
+      buildImplicitDependencies = "YES"
+      buildArchitectures = "Automatic">
+      <BuildActionEntries>
+         <BuildActionEntry
+            buildForTesting = "YES"
+            buildForRunning = "YES"
+            buildForProfiling = "YES"
+            buildForArchiving = "YES"
+            buildForAnalyzing = "YES">
+            <BuildableReference
+               BuildableIdentifier = "primary"
+               BlueprintIdentifier = "3FD1DFE32F0E00BF00A62733"
+               BuildableName = "playboy.app"
+               BlueprintName = "playboy"
+               ReferencedContainer = "container:ShenYin.xcodeproj">
+            </BuildableReference>
+         </BuildActionEntry>
+      </BuildActionEntries>
+   </BuildAction>
+   <TestAction
+      buildConfiguration = "Debug"
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      shouldUseLaunchSchemeArgsEnv = "YES"
+      shouldAutocreateTestPlan = "YES">
+   </TestAction>
+   <LaunchAction
+      buildConfiguration = "Debug"
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      launchStyle = "0"
+      useCustomWorkingDirectory = "NO"
+      ignoresPersistentStateOnLaunch = "NO"
+      debugDocumentVersioning = "YES"
+      debugServiceExtension = "internal"
+      allowLocationSimulation = "YES">
+      <BuildableProductRunnable
+         runnableDebuggingMode = "0">
+         <BuildableReference
+            BuildableIdentifier = "primary"
+            BlueprintIdentifier = "3FD1DFE32F0E00BF00A62733"
+            BuildableName = "playboy.app"
+            BlueprintName = "playboy"
+            ReferencedContainer = "container:ShenYin.xcodeproj">
+         </BuildableReference>
+      </BuildableProductRunnable>
+   </LaunchAction>
+   <ProfileAction
+      buildConfiguration = "Release"
+      shouldUseLaunchSchemeArgsEnv = "YES"
+      savedToolIdentifier = ""
+      useCustomWorkingDirectory = "NO"
+      debugDocumentVersioning = "YES">
+      <BuildableProductRunnable
+         runnableDebuggingMode = "0">
+         <BuildableReference
+            BuildableIdentifier = "primary"
+            BlueprintIdentifier = "3FD1DFE32F0E00BF00A62733"
+            BuildableName = "playboy.app"
+            BlueprintName = "playboy"
+            ReferencedContainer = "container:ShenYin.xcodeproj">
+         </BuildableReference>
+      </BuildableProductRunnable>
+   </ProfileAction>
+   <AnalyzeAction
+      buildConfiguration = "Debug">
+   </AnalyzeAction>
+   <ArchiveAction
+      buildConfiguration = "Release"
+      revealArchiveInOrganizer = "YES">
+   </ArchiveAction>
+</Scheme>
diff --git a/ShenYin/ShenYin/Assets.xcassets/device/pip_close.imageset/Contents.json b/ShenYin/ShenYin/Assets.xcassets/device/pip_close.imageset/Contents.json
new file mode 100644 (file)
index 0000000..3fd78ab
--- /dev/null
@@ -0,0 +1,22 @@
+{
+  "images" : [
+    {
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "filename" : "Slice 49@2x.png",
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "filename" : "Slice 49@3x.png",
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}
diff --git a/ShenYin/ShenYin/Assets.xcassets/device/pip_close.imageset/Slice 49@2x.png b/ShenYin/ShenYin/Assets.xcassets/device/pip_close.imageset/Slice 49@2x.png
new file mode 100644 (file)
index 0000000..f21e71b
Binary files /dev/null and b/ShenYin/ShenYin/Assets.xcassets/device/pip_close.imageset/Slice 49@2x.png differ
diff --git a/ShenYin/ShenYin/Assets.xcassets/device/pip_close.imageset/Slice 49@3x.png b/ShenYin/ShenYin/Assets.xcassets/device/pip_close.imageset/Slice 49@3x.png
new file mode 100644 (file)
index 0000000..ab93842
Binary files /dev/null and b/ShenYin/ShenYin/Assets.xcassets/device/pip_close.imageset/Slice 49@3x.png differ
diff --git a/ShenYin/ShenYin/Assets.xcassets/device/pip_set.imageset/Contents.json b/ShenYin/ShenYin/Assets.xcassets/device/pip_set.imageset/Contents.json
new file mode 100644 (file)
index 0000000..dcf07d8
--- /dev/null
@@ -0,0 +1,22 @@
+{
+  "images" : [
+    {
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "filename" : "Slice 47@2x.png",
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "filename" : "Slice 47@3x.png",
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}
diff --git a/ShenYin/ShenYin/Assets.xcassets/device/pip_set.imageset/Slice 47@2x.png b/ShenYin/ShenYin/Assets.xcassets/device/pip_set.imageset/Slice 47@2x.png
new file mode 100644 (file)
index 0000000..4b11b18
Binary files /dev/null and b/ShenYin/ShenYin/Assets.xcassets/device/pip_set.imageset/Slice 47@2x.png differ
diff --git a/ShenYin/ShenYin/Assets.xcassets/device/pip_set.imageset/Slice 47@3x.png b/ShenYin/ShenYin/Assets.xcassets/device/pip_set.imageset/Slice 47@3x.png
new file mode 100644 (file)
index 0000000..781374a
Binary files /dev/null and b/ShenYin/ShenYin/Assets.xcassets/device/pip_set.imageset/Slice 47@3x.png differ
index 03dc84d..9743358 100644 (file)
@@ -173,7 +173,13 @@ extension HomeDeviceVC:UICollectionViewDataSource,UICollectionViewDelegate,UICol
     }
     func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
         let model = DeviceVM.shared.dataList[indexPath.row]
-        App.shared.goToPage(AiFunctionVC(device: model))
+//        App.shared.goToPage(AiFunctionVC(device: model))
+        
+        if #available(iOS 15.0, *) {
+            App.shared.goToPage(SubTitleVC())
+        } else {
+            // Fallback on earlier versions
+        }
         
     }
     func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView{
index 8ca32a3..936acd4 100644 (file)
@@ -51,9 +51,9 @@
                <string>bluetooth-central</string>
                <string>audio</string>
        </array>
-       <key>UIViewControllerBasedStatusBarAppearance</key>
-       <true/>
        <key>UIDesignRequiresCompatibility</key>
        <true/>
+       <key>UIViewControllerBasedStatusBarAppearance</key>
+       <true/>
 </dict>
 </plist>
index ebd434e..a6716ae 100644 (file)
@@ -19,7 +19,7 @@ class BaseTC:UITabBarController{
     func setupUI(){
         if CCDevice.isJoy{
             let homeVC = HomeDeviceVC()
-//            let homeVC = CustomerVC()
+            
 
             let modeVC = ModeVC()
             let sleepVC = SleepVC()
diff --git a/ShenYin/ShenYin/UI/Home/SubTitle/LanguagePickerView1.swift b/ShenYin/ShenYin/UI/Home/SubTitle/LanguagePickerView1.swift
new file mode 100644 (file)
index 0000000..636af0b
--- /dev/null
@@ -0,0 +1,306 @@
+//
+//  Untitled.swift
+//  ShenYin
+//
+//  Created by liangshi on 2026/3/5.
+//
+
+import UIKit
+import JoyGemAI
+@available(iOS 15.0, *)
+// MARK: - 数据模型
+struct LanguageModel {
+    
+    let code: String
+    let name: String
+    let nativeName: String
+    
+    static let chinese = LanguageModel(code: kJoyGemAILocalizationZH, name: "Chinese", nativeName: "中文")
+    static let english = LanguageModel(code: kJoyGemAILocalizationEN, name: "English", nativeName: "英语")
+    static let japanese = LanguageModel(code: kJoyGemAILocalizationJA, name: "Japanese", nativeName: "日本語")
+    static let korean = LanguageModel(code: kJoyGemAILocalizationKO, name: "Korean", nativeName: "韩语")
+    static let french = LanguageModel(code: kJoyGemAILocalizationFR, name: "French", nativeName: "法语")
+    static let spanish = LanguageModel(code: kJoyGemAILocalizationES, name: "Spanish", nativeName: "西班牙语")
+    static let portuguese = LanguageModel(code: kJoyGemAILocalizationPT, name: "Portuguese", nativeName: "葡萄牙语")
+    static let indonesia = LanguageModel(code: kJoyGemAILocalizationID, name: "Indonesia", nativeName: "印尼语")
+    static let russian_ori = LanguageModel(code: kJoyGemAILocalizationRU_Original, name: "Russian", nativeName: "俄语")
+    static let russian_tar = LanguageModel(code: kJoyGemAILocalizationRU_Target, name: "Russian", nativeName: "俄语")
+    static let malay = LanguageModel(code: kJoyGemAILocalizationMS, name: "Malay", nativeName: "马来语")
+    static let german = LanguageModel(code: kJoyGemAILocalizationDE, name: "German", nativeName: "德语")
+    static let filipino = LanguageModel(code: kJoyGemAILocalizationFIL, name: "Filipino", nativeName: "菲律宾语")
+    static let thai = LanguageModel(code: kJoyGemAILocalizationTH, name: "Thai", nativeName: "泰语")
+    static let arabic = LanguageModel(code: kJoyGemAILocalizationAR, name: "Arabic", nativeName: "阿拉伯语")
+    static let vietnamese = LanguageModel(code: kJoyGemAILocalizationVI, name: "Vietnamese", nativeName: "越南语")
+}
+
+// 语言选择器的委托协议
+@available(iOS 15.0, *)
+protocol LanguagePickerView1Delegate: AnyObject {
+    
+    func languagePickerView(_ pickerView: LanguagePickerView1,
+                            didSelectSourceLanguage source: LanguageModel,
+                            targetLanguage target: LanguageModel)
+    
+    func languagePickerViewDidTapSwap(_ pickerView: LanguagePickerView1)
+}
+@available(iOS 15.0, *)
+class LanguagePickerView1: UIView {
+    
+    // MARK: - UI 组件
+    private let sourcePickerView = UIPickerView()
+    private let targetPickerView = UIPickerView()
+    private let swapButton = UIButton(type: .system)
+    private let sourceLabel = UILabel()
+    private let targetLabel = UILabel()
+    
+    // MARK: - 属性
+    weak var delegate: LanguagePickerView1Delegate?
+    
+    var selectedSourceLanguage: LanguageModel? {
+        didSet { updateSelection() }
+    }
+    
+    var selectedTargetLanguage: LanguageModel? {
+        didSet { updateSelection() }
+    }
+    
+    var languages: [LanguageModel] = [
+        .chinese, .english, .japanese,.korean,.french,.spanish,.portuguese,.indonesia,.russian_ori,.malay,.german,.filipino,.thai,.arabic,.vietnamese
+    ]
+    
+    // MARK: - 初始化
+    override init(frame: CGRect) {
+        super.init(frame: frame)
+        setupUI()
+        setupDefaults()
+    }
+    
+    required init?(coder: NSCoder) {
+        super.init(coder: coder)
+        setupUI()
+        setupDefaults()
+    }
+    
+    // MARK: - UI 设置
+    private func setupUI() {
+        backgroundColor = .systemBackground
+        
+        setupLabels()
+        setupPickerViews()
+        setupSwapButton()
+        setupConstraints()
+    }
+    
+    private func setupLabels() {
+        sourceLabel.text = "源语言"
+        sourceLabel.font = UIFont.boldSystemFont(ofSize: 16)
+        sourceLabel.textAlignment = .center
+        addSubview(sourceLabel)
+        
+        targetLabel.text = "目标语言"
+        targetLabel.font = UIFont.boldSystemFont(ofSize: 16)
+        targetLabel.textAlignment = .center
+        addSubview(targetLabel)
+    }
+    
+    private func setupPickerViews() {
+        // 源语言选择器
+        sourcePickerView.translatesAutoresizingMaskIntoConstraints = false
+        sourcePickerView.dataSource = self
+        sourcePickerView.delegate = self
+        sourcePickerView.tag = 0
+        addSubview(sourcePickerView)
+        
+        // 目标语言选择器
+        targetPickerView.translatesAutoresizingMaskIntoConstraints = false
+        targetPickerView.dataSource = self
+        targetPickerView.delegate = self
+        targetPickerView.tag = 1
+        addSubview(targetPickerView)
+    }
+    
+    private func setupSwapButton() {
+        swapButton.translatesAutoresizingMaskIntoConstraints = false
+        swapButton.setImage(UIImage(systemName: "arrow.left.arrow.right"), for: .normal)
+        swapButton.tintColor = .systemBlue
+        swapButton.backgroundColor = .systemGray6
+        swapButton.layer.cornerRadius = 20
+        swapButton.addTarget(self, action: #selector(swapButtonTapped), for: .touchUpInside)
+        addSubview(swapButton)
+    }
+    
+    private func setupConstraints() {
+        sourceLabel.snp.makeConstraints { make in
+            make.top.equalToSuperview().offset(8)
+            make.leading.equalToSuperview().offset(20)
+            make.trailing.equalTo(swapButton.snp.leading).offset(-20)
+            make.height.equalTo(20)
+        }
+        
+        targetLabel.snp.makeConstraints { make in
+            make.top.equalToSuperview().offset(8)
+            make.trailing.equalToSuperview().offset(-20)
+            make.leading.equalTo(swapButton.snp.trailing).offset(20)
+            make.height.equalTo(20)
+        }
+        
+        sourcePickerView.snp.makeConstraints { make in
+            make.top.equalTo(sourceLabel.snp.bottom).offset(8)
+            make.leading.equalToSuperview().offset(20)
+            make.trailing.equalTo(swapButton.snp.leading).offset(-20)
+            make.bottom.equalToSuperview().offset(-8)
+        }
+        
+        targetPickerView.snp.makeConstraints { make in
+            make.top.equalTo(targetLabel.snp.bottom).offset(8)
+            make.trailing.equalToSuperview().offset(-20)
+            make.leading.equalTo(swapButton.snp.trailing).offset(20)
+            make.bottom.equalToSuperview().offset(-8)
+        }
+        
+        swapButton.snp.makeConstraints { make in
+            make.centerX.equalToSuperview()
+            make.centerY.equalTo(sourcePickerView.snp.centerY)
+            make.height.equalTo(40)
+            make.width.equalTo(40)
+        }
+    }
+    
+    private func setupDefaults() {
+        // 设置默认选择
+        if let chineseIndex = languages.firstIndex(where: { $0.code == "zh" }) {
+            sourcePickerView.selectRow(chineseIndex, inComponent: 0, animated: false)
+            selectedSourceLanguage = languages[chineseIndex]
+        }
+        
+        if let englishIndex = languages.firstIndex(where: { $0.code == "en" }) {
+            targetPickerView.selectRow(englishIndex, inComponent: 0, animated: false)
+            selectedTargetLanguage = languages[englishIndex]
+        }
+    }
+    
+    // MARK: - 公共方法
+    func setLanguages(source: LanguageModel, target: LanguageModel) {
+        if let sourceIndex = languages.firstIndex(where: { $0.code == source.code }) {
+            sourcePickerView.selectRow(sourceIndex, inComponent: 0, animated: true)
+            selectedSourceLanguage = source
+        }
+        
+        if let targetIndex = languages.firstIndex(where: { $0.code == target.code }) {
+            targetPickerView.selectRow(targetIndex, inComponent: 0, animated: true)
+            selectedTargetLanguage = target
+        }
+    }
+    
+    func getSelectedLanguages() -> (source: LanguageModel?, target: LanguageModel?) {
+        return (selectedSourceLanguage, selectedTargetLanguage)
+    }
+    
+    // MARK: - 私有方法
+    private func updateSelection() {
+        // 可以在这里添加选择更新后的逻辑
+        print("源语言: \(selectedSourceLanguage?.nativeName ?? "无")")
+        print("目标语言: \(selectedTargetLanguage?.nativeName ?? "无")")
+        
+        // 通知委托
+        if let source = selectedSourceLanguage, let target = selectedTargetLanguage {
+            delegate?.languagePickerView(self, didSelectSourceLanguage: source, targetLanguage: target)
+        }
+    }
+    
+    @objc private func swapButtonTapped() {
+        guard let source = selectedSourceLanguage,
+              let target = selectedTargetLanguage else { return }
+        
+        // 交换语言
+        setLanguages(source: target, target: source)
+        
+        // 通知委托
+        delegate?.languagePickerViewDidTapSwap(self)
+    }
+}
+
+// MARK: - UIPickerView DataSource & Delegate
+@available(iOS 15.0, *)
+extension LanguagePickerView1: UIPickerViewDataSource, UIPickerViewDelegate {
+    
+    func numberOfComponents(in pickerView: UIPickerView) -> Int {
+        return 1
+    }
+    
+    func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
+        return languages.count
+    }
+    
+    func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
+        let language = languages[row]
+        return "\(language.nativeName) (\(language.name))"
+    }
+    
+    func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
+        let selectedLanguage = languages[row]
+        
+        if pickerView.tag == 0 {
+            selectedSourceLanguage = selectedLanguage
+        } else {
+            selectedTargetLanguage = selectedLanguage
+        }
+        
+        // 防止选择相同的语言
+        validateSelection()
+    }
+    
+    func pickerView(_ pickerView: UIPickerView, rowHeightForComponent component: Int) -> CGFloat {
+        return 44.0
+    }
+    
+    func pickerView(_ pickerView: UIPickerView, viewForRow row: Int, forComponent component: Int, reusing view: UIView?) -> UIView {
+        let language = languages[row]
+        
+        let containerView = UIView()
+        containerView.backgroundColor = .clear
+        
+        let stackView = UIStackView()
+        stackView.axis = .vertical
+        stackView.alignment = .center
+        stackView.spacing = 2
+        stackView.translatesAutoresizingMaskIntoConstraints = false
+        
+        let nativeLabel = UILabel()
+        nativeLabel.text = language.nativeName
+        nativeLabel.font = UIFont.systemFont(ofSize: 16, weight: .medium)
+        nativeLabel.textAlignment = .center
+        nativeLabel.textColor = .label
+        
+        let nameLabel = UILabel()
+        nameLabel.text = language.name
+        nameLabel.font = UIFont.systemFont(ofSize: 12, weight: .regular)
+        nameLabel.textColor = .secondaryLabel
+        nameLabel.textAlignment = .center
+        
+        stackView.addArrangedSubview(nativeLabel)
+        stackView.addArrangedSubview(nameLabel)
+        containerView.addSubview(stackView)
+        
+        NSLayoutConstraint.activate([
+            stackView.centerXAnchor.constraint(equalTo: containerView.centerXAnchor),
+            stackView.centerYAnchor.constraint(equalTo: containerView.centerYAnchor),
+            stackView.leadingAnchor.constraint(equalTo: containerView.leadingAnchor, constant: 8),
+            stackView.trailingAnchor.constraint(equalTo: containerView.trailingAnchor, constant: -8)
+        ])
+        
+        return containerView
+    }
+    
+    private func validateSelection() {
+        guard let source = selectedSourceLanguage,
+              let target = selectedTargetLanguage,
+              source.code == target.code else { return }
+        
+        // 如果选择了相同的语言,自动调整目标语言
+        if let alternativeIndex = languages.firstIndex(where: { $0.code != source.code }) {
+            targetPickerView.selectRow(alternativeIndex, inComponent: 0, animated: true)
+            selectedTargetLanguage = languages[alternativeIndex]
+        }
+    }
+}
diff --git a/ShenYin/ShenYin/UI/Home/SubTitle/PiPManager.swift b/ShenYin/ShenYin/UI/Home/SubTitle/PiPManager.swift
new file mode 100644 (file)
index 0000000..99aabad
--- /dev/null
@@ -0,0 +1,175 @@
+//
+//  Untitled.swift
+//  ShenYin
+//
+//  Created by liangshi on 2026/3/5.
+//
+
+import AVKit
+import UIKit
+
+@available(iOS 15.0, *)
+class PiPManager: NSObject, ObservableObject {
+    
+    var pipController: AVPictureInPictureController?
+    
+    var contentVC: DesktopLyricsContentVC!
+    
+    var messageList : [(String,UInt)] = []
+    
+    var translateList : [(String,UInt)] = []
+    
+    func setupPictureInPicture(sourceView : UIView) {
+
+        contentVC = DesktopLyricsContentVC()
+        contentVC.preferredContentSize = CGSize(width: UIScreen.main.bounds.width, height: 240) // 画中画窗口大小
+        
+        // 设置播放器
+        pipController = AVPictureInPictureController(contentSource: AVPictureInPictureController.ContentSource(
+            activeVideoCallSourceView: sourceView,
+            contentViewController: contentVC
+        ))
+        pipController?.delegate = self
+    }
+
+    
+    func startPictureInPicture() {
+        // 1. 检查场景状态
+        if let scene = UIApplication.shared.connectedScenes.first as? UIWindowScene {
+            print("场景激活状态: \(scene.activationState.rawValue)")
+            print("场景状态描述: \(describeActivationState(scene.activationState))")
+        } else {
+            print("❌ 无法获取场景")
+        }
+        
+        pipController?.startPictureInPicture()
+    }
+    
+    private func describeActivationState(_ state: UIScene.ActivationState) -> String {
+        switch state {
+        case .unattached: return "unattached - 场景未连接到会话"
+        case .foregroundInactive: return "foregroundInactive - 前景但不活跃"
+        case .foregroundActive: return "foregroundActive - 前景且活跃 ✅"
+        case .background: return "background - 后台"
+        @unknown default: return "unknown"
+        }
+    }
+    
+    func stopPictureInPicture() {
+        pipController?.stopPictureInPicture()
+    }
+    
+    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")
+        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")
+        contentVC?.updateTrans(res)
+    }
+}
+
+@available(iOS 15.0, *)
+extension PiPManager: AVPictureInPictureControllerDelegate {
+    func pictureInPictureControllerWillStartPictureInPicture(_ pictureInPictureController: AVPictureInPictureController) {
+        print("画中画即将开始")
+    }
+    
+    func pictureInPictureControllerDidStartPictureInPicture(_ pictureInPictureController: AVPictureInPictureController) {
+        print("画中画已开始")
+        // 开始播放透明视频
+        //player?.play()
+    }
+    
+    func pictureInPictureController(_ pictureInPictureController: AVPictureInPictureController, failedToStartPictureInPictureWithError error: Error) {
+        print("画中画启动失败: \(error)")
+    }
+    
+    
+    func pictureInPictureControllerDidStopPictureInPicture(_ pictureInPictureController: AVPictureInPictureController) {
+        print("画中画已结束")
+//        messageList.removeAll()
+//        translateList.removeAll()
+    }
+}
+// 画中画内容视图控制器
+@available(iOS 15.0, *)
+class DesktopLyricsContentVC : AVPictureInPictureVideoCallViewController {
+    let setView = PipSetView()
+    var textView = UITextView()
+    var translateTextView = UITextView()
+    
+    override func viewDidLoad() {
+        super.viewDidLoad()
+        setupViews()
+        setupLayout()
+    }
+    func setupViews(){
+        view.addSubviews([setView,textView,translateTextView])
+        
+        textView.do { v in
+            v.textColor = UIColor.white
+            v.text = "原文"
+            v.font = UIFont.boldSystemFont(ofSize: 14)
+            v.backgroundColor = UIColor.gray
+        }
+        
+        translateTextView.do { v in
+            v.textColor = UIColor.orange
+            v.text = "翻译"
+            v.font = UIFont.boldSystemFont(ofSize: 14)
+            v.backgroundColor = UIColor.gray
+        }
+    }
+    func setupLayout(){
+        setView.snp.makeConstraints { make in
+            make.left.right.equalToSuperview()
+            make.height.equalTo(34)
+            make.top.equalToSuperview()
+        }
+        textView.snp.makeConstraints { make in
+            make.top.equalToSuperview().inset(40)
+            make.leading.trailing.equalToSuperview()
+            make.bottom.equalTo(view.snp.centerY)
+        }
+        translateTextView.snp.makeConstraints { make in
+            make.leading.trailing.equalToSuperview()
+            make.top.equalTo(textView.snp.bottom)
+            make.height.equalTo(textView.snp.height)
+        }
+        
+    }
+    
+    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))
+    }
+}
diff --git a/ShenYin/ShenYin/UI/Home/SubTitle/PipPicker.swift b/ShenYin/ShenYin/UI/Home/SubTitle/PipPicker.swift
new file mode 100644 (file)
index 0000000..872364a
--- /dev/null
@@ -0,0 +1,164 @@
+//
+//  Untitled.swift
+//  ShenYin
+//
+//  Created by liangshi on 2026/3/6.
+//
+
+import UIKit
+class PipPicker: BaseView {
+    private let btn = UIButton(type: .custom)
+    private let tableView = UITableView(frame: .zero, style: .plain)
+    var list:[String] = []
+
+    var selectedIndex = 0{
+        didSet{
+            tableView.reloadData()
+        }
+    }
+    var didSelected: ((Int,String)->Void)?
+    private var title:String = ""
+    
+    init(list:[String]) {
+        super.init(frame: .zero)
+    }
+    
+    @MainActor required init?(coder: NSCoder) {
+        fatalError("init(coder:) has not been implemented")
+    }
+    
+    override func setupViews() {
+        addSubviews([btn,tableView])
+        
+        btn.do { v in
+            v.setImage(UIImage(named: "close_icon"), for: .normal)
+            v.addTarget(self, action: #selector(closeAction), for: .touchUpInside)
+        }
+        tableView.do { v in
+            v.backgroundColor = .color(.cellBg)
+            v.delegate = self
+            v.dataSource = self
+            v.rowHeight = 52
+            v.separatorStyle = .none
+            v.register(CustomButton.SelectCell.self, forCellReuseIdentifier: CustomButton.SelectCell.reuseID)
+        }
+    }
+    override func setupLayout() {
+        super.setupLayout()
+        btn.snp.makeConstraints { (m) in
+            m.bottom.equalToSuperview()
+            m.right.equalToSuperview()
+            m.size.equalTo(60)
+        }
+        tableView.snp.makeConstraints { make in
+            make.left.right.bottom.equalToSuperview()
+            make.top.equalToSuperview().inset(10)
+        }
+    }
+    @objc func closeAction(){
+        
+    }
+}
+extension PipPicker:UITableViewDelegate,UITableViewDataSource {
+    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
+        return list.count
+    }
+    
+    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
+        let cell = CustomButton.SelectCell.cell(withTableView: tableView, indexPath: indexPath)
+        cell.titleLabel.text = list[indexPath.row]
+        cell.selectedIcon.isHidden = selectedIndex != indexPath.row
+        return cell
+    }
+    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
+        selectedIndex = indexPath.row
+        tableView.reloadData()
+        didSelected?(selectedIndex,list[selectedIndex])
+    }
+}
+
+fileprivate extension CustomButton {
+    class SelectCell: BaseTableViewCell {
+        let bgView = UIView()
+        let titleLabel = UILabel()
+        let selectedIcon = UIImageView()
+        let line = UIView()
+        
+        var fontType:FontType = .min{
+            didSet{
+                titleLabel.text = fontType.title
+            }
+        }
+        
+        var shareType:ShareType = .document{
+            didSet{
+                titleLabel.text = shareType.title
+            }
+        }
+        
+        var enable:Bool = true{
+            didSet{
+                if enable{
+                    titleLabel.textColor = .color(.first)
+                }
+                else{
+                    titleLabel.textColor = .color(.secondary)
+                }
+            }
+        }
+        override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
+            super.init(style: style, reuseIdentifier: reuseIdentifier)
+        }
+        
+        required init?(coder: NSCoder) {
+            fatalError("init(coder:) has not been implemented")
+        }
+        override func setupViews() {
+            contentView.addSubview(bgView)
+            bgView.addSubviews([titleLabel,selectedIcon,line])
+            
+            backgroundColor = .color(.bgColor)
+            contentView.backgroundColor = .clear
+            selectionStyle = .none
+            bgView.do { v in
+                v.backgroundColor = .color(.cellBg)
+            }
+            titleLabel.do { (v) in
+                v.textColor = .color(.first)
+                v.font = .bold(14)
+                v.textAlignment = .left
+            }
+            
+            selectedIcon.image = UIImage(named: "cell_selected")
+            line.do { v in
+                v.backgroundColor = .color(.separateLine)
+            }
+        }
+        
+        override func setupLayout() {
+            bgView.snp.makeConstraints { (m) in
+                m.left.right.equalToSuperview()
+                m.top.equalToSuperview()
+                m.bottom.equalToSuperview()
+            }
+            selectedIcon.snp.makeConstraints { (m) in
+                m.width.equalTo(21)
+                m.height.equalTo(16)
+                m.right.equalToSuperview().inset(21)
+                m.centerY.equalToSuperview()
+            }
+            titleLabel.snp.makeConstraints { (m) in
+                m.centerY.equalToSuperview()
+                m.left.equalToSuperview().offset(24)
+                m.height.equalToSuperview()
+            }
+            line.snp.makeConstraints { make in
+                make.left.right.equalToSuperview().inset(18)
+                make.bottom.equalToSuperview()
+                make.height.equalTo(0.4)
+            }
+        }
+    }
+    
+}
+
diff --git a/ShenYin/ShenYin/UI/Home/SubTitle/PipSetView.swift b/ShenYin/ShenYin/UI/Home/SubTitle/PipSetView.swift
new file mode 100644 (file)
index 0000000..8d66cd3
--- /dev/null
@@ -0,0 +1,77 @@
+//
+//  PipSetView.swift
+//  ShenYin
+//
+//  Created by liangshi on 2026/3/6.
+//
+
+class PipSetView: BaseView {
+    let setBtn = UIButton(type: .custom)
+    let closeBtn = UIButton(type: .custom)
+    let languageItem =  UIButton(type: .custom)
+    let dispalyItem =  UIButton(type: .custom)
+    
+    override func setupViews() {
+        addSubviews([setBtn,languageItem,dispalyItem,closeBtn])
+        
+        setBtn.do { v in
+            v.setImage(UIImage(named: "pip_set"), for: .normal)
+            v.addTarget(self, action: #selector(setBtnAction), for: .touchUpInside)
+        }
+        closeBtn.do { v in
+            v.setImage(UIImage(named: "pip_close"), for: .normal)
+            v.addTarget(self, action: #selector(closeAction), for: .touchUpInside)
+        }
+        languageItem.do { v in
+            v.setTitle("", for: .normal)
+            v.addTarget(self, action: #selector(languageAction), for: .touchUpInside)
+            v.yc.setCornerRadius(12)
+            v.backgroundColor = .red
+        }
+        dispalyItem.do { v in
+            v.setTitle("", for: .normal)
+            v.addTarget(self, action: #selector(displayAction), for: .touchUpInside)
+            v.yc.setCornerRadius(12)
+            v.backgroundColor = .red
+        }
+    }
+    override func setupLayout() {
+        setBtn.snp.makeConstraints { make in
+            make.size.equalTo(24)
+            make.left.equalToSuperview().inset(16)
+            make.top.equalToSuperview().inset(10)
+        }
+        closeBtn.snp.makeConstraints { make in
+            make.size.equalTo(24)
+            make.right.equalToSuperview().inset(16)
+            make.centerY.equalTo(setBtn)
+        }
+        languageItem.snp.makeConstraints { make in
+            make.height.equalTo(24)
+            make.left.equalTo(setBtn.snp.right).offset(4)
+            make.centerY.equalTo(setBtn)
+            make.width.equalTo(57)
+        }
+        dispalyItem.snp.makeConstraints { make in
+            make.height.equalTo(24)
+            make.left.equalTo(languageItem.snp.right).offset(4)
+            make.centerY.equalTo(setBtn)
+            make.width.equalTo(57)
+        }
+    }
+    @objc func setBtnAction(){
+        Logger.debug("setBtnAction")
+    }
+    @objc func languageAction(){
+        Logger.debug("languageAction")
+    }
+    @objc func displayAction(){
+        Logger.debug("displayAction")
+        let view = PipPicker(list: ["只显示原文","只显译文","原文 & 译文"])
+        superview?.addSubview(view)
+    }
+    @objc func closeAction(){
+        Logger.debug("closeAction")
+        
+    }
+}
diff --git a/ShenYin/ShenYin/UI/Home/SubTitle/SubTitleVC.swift b/ShenYin/ShenYin/UI/Home/SubTitle/SubTitleVC.swift
new file mode 100644 (file)
index 0000000..915eed2
--- /dev/null
@@ -0,0 +1,186 @@
+//
+//  Untitled.swift
+//  ShenYin
+//
+//  Created by liangshi on 2026/3/5.
+//
+
+
+import UIKit
+import AVKit
+import JoyGemAI
+import SVProgressHUD
+@available(iOS 15.0, *)
+class SubTitleVC: UIViewController {
+    
+    lazy var languagePickerView : LanguagePickerView1 = {
+        let pickerView = LanguagePickerView1()
+        pickerView.delegate = self
+        return pickerView
+    }()
+    
+    var startButton : UIButton!
+    
+    var stopButton : UIButton!
+    let pipManager = PiPManager()
+
+    
+    //画中画载体
+    internal var customView : UIView = UIView()
+    
+    override func viewDidLoad() {
+        super.viewDidLoad()
+        view.backgroundColor = UIColor.white
+        title = "字幕翻译"
+        
+        self.navigationController?.navigationBar.tintColor = UIColor.black
+        do {
+            try AVAudioSession.sharedInstance().setCategory(.playback)
+            try AVAudioSession.sharedInstance().setActive(true)
+        } catch {
+            print(error)
+        }
+        
+        view.addSubview(languagePickerView)
+        languagePickerView.snp.makeConstraints { make in
+            make.top.equalTo(view.safeAreaLayoutGuide.snp.top)
+            make.leading.trailing.equalToSuperview()
+            make.height.equalTo(100)
+        }
+        
+        // 或者设置特定语言
+        languagePickerView.setLanguages(
+            source: LanguageModel.chinese,
+            target: LanguageModel.english
+        )
+        
+        view.addSubview(customView)
+        customView.snp.makeConstraints { make in
+            make.top.equalTo(languagePickerView.snp.bottom).offset(20)
+            make.height.equalTo(40)
+            make.centerX.equalToSuperview()
+            make.width.equalTo(200)
+        }
+        
+        startButton = UIButton(type: .system)
+        startButton.setTitle("开始", for: .normal)
+        startButton.backgroundColor = UIColor.systemGray6
+        startButton.setTitleColor(UIColor.darkText, for: .normal)
+        startButton.addTarget(self, action: #selector(startRecord), for: .touchUpInside)
+        
+        stopButton = UIButton(type: .system)
+        stopButton.setTitle("结束", for: .normal)
+        stopButton.backgroundColor = UIColor.systemGray6
+        stopButton.setTitleColor(UIColor.darkText, for: .normal)
+        stopButton.addTarget(self, action: #selector(endRecord), for: .touchUpInside)
+        
+        let stackView = UIStackView(arrangedSubviews: [startButton, stopButton])
+        stackView.axis = .horizontal
+        stackView.distribution = .fillEqually
+        stackView.alignment = .center
+        stackView.spacing = 16
+        
+        view.addSubview(stackView)
+        stackView.snp.makeConstraints { make in
+            make.height.equalTo(60)
+            make.leading.equalToSuperview().offset(20)
+            make.trailing.equalToSuperview().offset(-20)
+            make.bottom.equalTo(view.safeAreaLayoutGuide.snp.bottom).offset(-20)
+        }
+        
+        // Do any additional setup after loading the view.
+        JoyGemSubtitleManager.shared().delegate = self
+        
+        setupPiPManager()
+    }
+    
+    private func setupPiPManager() {
+        // 初始化画中画管理器
+        pipManager.setupPictureInPicture(sourceView: self.customView)
+        
+        // 监听画中画状态变化
+        NotificationCenter.default.addObserver(
+            self,
+            selector: #selector(pipStateChanged(_:)),
+            name: NSNotification.Name("PiPStateChanged"),
+            object: nil
+        )
+    }
+    
+    @objc func startRecord() {
+        JoyGemSubtitleManager.shared().start()
+        
+        guard AVPictureInPictureController.isPictureInPictureSupported() else {
+            print("设备不支持画中画")
+            return
+        }
+        
+        pipManager.startPictureInPicture()
+    }
+    
+    @objc func endRecord() {
+        JoyGemSubtitleManager.shared().stop()
+        
+        pipManager.stopPictureInPicture()
+    }
+    
+    @objc private func pipStateChanged(_ notification: Notification) {
+        if let userInfo = notification.userInfo,
+           let isActive = userInfo["isActive"] as? Bool {
+            print("画中画状态: \(isActive ? "活跃" : "非活跃")")
+        }
+    }
+}
+
+// 实现委托方法
+@available(iOS 15.0, *)
+extension SubTitleVC: LanguagePickerView1Delegate {
+    
+    func languagePickerView(_ pickerView: LanguagePickerView1,
+                            didSelectSourceLanguage source: LanguageModel,
+                            targetLanguage target: LanguageModel) {
+        print("语言选择更新: \(source.nativeName) -> \(target.nativeName)")
+        // 更新你的翻译逻辑等
+        JoyGemSubtitleManager.shared().originalLanguage = source.code
+        JoyGemSubtitleManager.shared().targetLanguage = target.code
+    }
+    
+    func languagePickerViewDidTapSwap(_ pickerView: LanguagePickerView1) {
+        print("交换了语言")
+    }
+}
+
+@available(iOS 15.0, *)
+extension SubTitleVC : JoyGemSubtitleManagerDelegate {
+    
+    func subtitleManager(_ manager: JoyGemSubtitleManager, didUpdateRaw model: JoyGemAsrModel) {
+        debugPrint("text: \(model.text),index: \(model.index)")
+        pipManager.updateRaw(model.text,model.index)
+    }
+    
+    func subtitleManager(_ manager: JoyGemSubtitleManager, didUpdateTranslate model: JoyGemAsrModel) {
+        debugPrint("translate text: \(model.text),index: \(model.index)")
+        pipManager.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) {
+        
+    }
+    
+}