【android】oppo手机拷贝视频文件

  • oppo 至今没有一个助手,

  • 有一个助手是升级系统的

  • 有一个connect实际上是做镜像手机屏幕的

  • 当然,也能监控文件变化

  • 对于我有一个camera文件夹2000个文件

  • 导致我每次不开着手机,导出文件到pc经常会断开连接。

  • 然后如果重新connect,会到处一堆xxx(1) 这样的文件

  • 完全没有什么 断点续传、文件存在检测这样的功能

  • 可见oppo 是没有以顾客为中心啊。

  • 插入usb传输文件后,

  • copilot 帮写了一个检测文件名是否存在,存在则复制到我的备份磁盘,不存在,那么跳过的代码:

dump_videos.py

  • D:\XTRANS\cuda\03-graph-db\04-cmkg\phone\dump_videos.py
python 复制代码
import win32com.client
import os
import time

def list_and_copy_videos(device_name, path_components, dest_root=None):
    shell = win32com.client.Dispatch("Shell.Application")
    # 17 = ssfDRIVES (This PC / My Computer)
    computer = shell.NameSpace(17)

    # Destination setup
    dest_shell_folder = None
    if dest_root:
        if not os.path.exists(dest_root):
            try:
                os.makedirs(dest_root)
            except OSError as e:
                print(f"Error creating destination directory '{dest_root}': {e}")
                return

        # Get Shell Folder for destination
        dest_shell_folder = shell.NameSpace(dest_root)
        if not dest_shell_folder:
            print(f"Error: Could not get ShellFolder for '{dest_root}'")
            return
        print(f"Destination folder ready: {dest_root}")

    current_folder = None

    # 1. Find the device in "This PC"
    print(f"Searching for device: {device_name} in 'This PC'...")
    # Note: If executed in a non-interactive session, ensure Shell.Application is available.

    found_device = False
    for item in computer.Items():
        # Using simple Name match. Sometimes display name might vary slightly.
        if item.Name == device_name:
            current_folder = item.GetFolder
            found_device = True
            break

    if not found_device:
        print(f"Error: Device '{device_name}' not found.")
        print("Available devices/drives (in 'This PC'):")
        for item in computer.Items():
            print(f" - {item.Name}")
        return

    # 2. Traverse the path components
    print(f"Device found. Navigating path: {' -> '.join(path_components)}")
    for component in path_components:
        found = False
        items = current_folder.Items()
        for item in items:
             if item.Name == component:
                 # Check if it is a folder. Note: Some MTP folders might report weird types, but IsFolder works usually.
                 if item.IsFolder:
                    current_folder = item.GetFolder
                    found = True
                    break

        if not found:
            print(f"Error: Folder '{component}' not found in '{current_folder.Title}'.")
            print("Available items in current folder:")
            for item in items:
                 # Only printing folders to reduce noise, or first 20 items
                 print(f" - {item.Name} {'[Dir]' if item.IsFolder else ''}")
            return

    print(f"Target folder reached: {current_folder.Title}")

    # 3. Recursively list and copy videos
    output_file = "video_list_3.txt"
    print(f"Scanning for videos (MOV, MP4, MKV, AVI, etc)...")

    if dest_root:
        print(f"Syncing to {dest_root}")

    video_extensions = (
        '.mov', '.mp4', '.m4v',
        '.mkv', '.webm', '.avi',
        '.3gp', '.ts', '.flv',
        '.wmv', '.asf'
    )

    stats = {
        'found': 0,
        'copied': 0,
        'skipped': 0,
        'errors': 0
    }

    found_videos_paths = []

    def recursive_scan(folder, relative_path):
        try:
            items = folder.Items()
        except Exception as e:
            print(f"Access denied or error reading folder {relative_path}: {e}")
            return

        for item in items:
            try:
                if item.IsFolder:
                    new_path = os.path.join(relative_path, item.Name)
                    # print(f"Scanning: {new_path}")
                    recursive_scan(item.GetFolder, new_path)
                else:
                    name = item.Name
                    if name.lower().endswith(video_extensions):
                        full_rel_path = os.path.join(relative_path, name)
                        stats['found'] += 1
                        found_videos_paths.append(full_rel_path)

                        if dest_root and dest_shell_folder:
                            # Flattened unique check: check if filename exists in dest_root
                            # (ignoring relative source path structure for the check, as requested "comparison with E:\...\files")
                            target_path = os.path.join(dest_root, name)

                            if os.path.exists(target_path):
                                print(f"[SKIP] {name} (already exists)")
                                stats['skipped'] += 1
                            else:
                                print(f"[COPY] {name} -> {target_path}")
                                try:
                                    # CopyHere flags:
                                    # 4 (no progress dialog) | 16 (yes to all) | 256 (simple progress)
                                    # Using 256 to show some Windows progress if it takes long, or 0 (default).
                                    # Since we are doing file by file, let's suppress UI if possible (4)
                                    # but MTP copy can be slow.
                                    dest_shell_folder.CopyHere(item, 16) # 16 = Respond to "Yes to All" for any dialog box

                                    # Very crude wait mechanism because CopyHere is async
                                    # Waiting for file to appear
                                    timeout = 60 # seconds
                                    start_wait = time.time()
                                    while not os.path.exists(target_path):
                                        time.sleep(0.5)
                                        if time.time() - start_wait > timeout:
                                            print(f"Warning: Timeout waiting for {name} to appear.")
                                            break

                                    # Optional: Check if size is growing? skipping for speed.
                                    # Just a small sleep to avoid flooding COM
                                    time.sleep(0.5)

                                    if os.path.exists(target_path):
                                         stats['copied'] += 1
                                    else:
                                         stats['errors'] += 1

                                except Exception as copy_err:
                                    print(f"Error copying {name}: {copy_err}")
                                    stats['errors'] += 1

            except Exception as e:
                # Sometimes accessing properties of MTP items fails randomly
                print(f"Error processing item: {e}")

    recursive_scan(current_folder, "")

    with open(output_file, "w", encoding="utf-8") as f:
        for v in found_videos_paths:
            f.write(v + "\n")

    print("-" * 40)
    print(f"Scan & Sync Complete.")
    print(f"Total Found: {stats['found']}")
    print(f"Copied:      {stats['copied']}")
    print(f"Skipped:     {stats['skipped']}")
    print(f"Errors:      {stats['errors']}")
    print(f"List saved to {os.path.abspath(output_file)}")

if __name__ == "__main__":
    # Required: pip install pywin32
    # Phone Name
    DEVICE_NAME = "OPPO Find X8s"

    # Source Path on Phone (MTP uses Names not drive letters)
    PATH_PARTS = ["内部共享存储空间", "DCIM", "Camera"]

    # Target Directory on PC
    # User requested: E:\20260127-视频
    TARGET_DIR = r"E:\20260127-视频"

    list_and_copy_videos(DEVICE_NAME, PATH_PARTS, dest_root=TARGET_DIR)
相关推荐
小羊没烦恼!4 天前
初探性能优化——2个月到4小时的性能提升
java·开发语言·windows·算法·c#
rockmelodies4 天前
# Windows Server2008 R2 Standard(SP1镜像U盘)重置本地管理员密码【完整详细步骤】
windows·密码破解
千里马学框架4 天前
一起学 Android 14:ShellTransition 屏幕旋转过程深度剖析
android·智能手机·性能优化·framework·性能·屏幕旋转·rotation
美狐美颜SDK开放平台4 天前
开发直播APP时如何接入视频美颜SDK?开发流程与注意事项
android·人工智能·计算机视觉·音视频·直播美颜sdk
AFinalStone4 天前
Android7 SystemUI源码解析(七)Keyguard锁屏模块深度解析
android·systemui
致远ccc4 天前
Google Play 上架前如何测试 App?多国家 Android 环境测试
android·app测试·googleplay·多国家应用测试
ttyyttemo4 天前
Kotlin 协程中的 Job 结构化并发与取消
android
sun0077004 天前
tbox 4g/5g切换,导致wan ip 改变,导致车机旧网络不可用。需要重启车机才行
android
其实防守也摸鱼4 天前
内网穿透与反向代理:原理、工具与实战指南
android·大数据·运维·安全·网络安全·自动化·渗透
AFinalStone4 天前
Android7 SystemUI 源码解析(四)NavigationBar 导航栏与 SystemBars
android·systemui