【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)
相关推荐
LeenixP2 小时前
OpenHarmony调试工具安装与使用-HDC
windows·测试工具·华为·鸿蒙系统·hdc
悠哉清闲2 小时前
android studio中怎么引用SVG
android·android studio
TheNextByte12 小时前
在小米上检索照片/视频的5种方法
android
我命由我123452 小时前
JUnit - 自定义 Rule
android·java·开发语言·数据库·junit·java-ee·android-studio
卜锦元2 小时前
Mac 上无痛使用 Windows 双系统的完整实践(Intel 或 Apple M芯片都可以)
windows·单片机·macos·金融·系统架构
多多*2 小时前
程序设计工作室1月28日内部训练赛 题解
java·开发语言·windows·哈希算法·散列表
2501_915921432 小时前
在没有源码的前提下,怎么对 Swift 做混淆,IPA 混淆
android·开发语言·ios·小程序·uni-app·iphone·swift
纽格立科技2 小时前
从模拟 FM 到数字 CDR:手机硬件架构为何难以跨越这道技术鸿沟
智能手机·硬件架构
海天一色y16 小时前
普利姆算法(Prim)和克鲁斯卡尔算法(Kruskal)
windows·算法