You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flet框架下能否使用本地资源播放MP4文件及实现方法

Flet框架下能否使用本地资源播放MP4文件及实现方法

嘿,你完全可以用Flet播放本地MP4文件的!官方文档里只放了HTTP资源的例子,只是因为本地路径依赖每个人的具体环境,不是不支持本地文件哦~我来给你讲讲具体的实现方法,以及排查你之前尝试失败的原因。

为什么你用./video/movie.mp4没生效?

大概率是路径匹配问题:相对路径是相对于你运行Python脚本时的工作目录,而不是脚本文件所在的目录。比如你在/Users/xxx目录下运行python Documents/flet_project/main.py,那脚本的工作目录是/Users/xxx,而不是/Users/xxx/Documents/flet_project,这时候./video/movie.mp4就会去/Users/xxx/video/movie.mp4找文件,自然找不到。

你可以先在代码里加一行打印确认工作目录:

import os
print("当前工作目录:", os.getcwd())

三种实现本地MP4播放的方法

方法1:直接使用绝对路径(最直接,适合测试)

直接写视频文件的完整绝对路径,Mac上的格式比如/Users/xxx/Documents/flet_project/video/movie.mp4,这样Flet能精准找到文件:

sample_media = [
    ft.VideoMedia(
        "/Users/xxx/Documents/flet_project/video/movie.mp4",
        extras={"artist": "本地测试视频", "album": "测试专辑"}
    )
]

方法2:修正相对路径(适合项目内文件)

如果视频文件和脚本在同一目录结构下,确保运行脚本时的工作目录是脚本所在目录:

  • 打开终端,先cd到脚本所在的文件夹,再运行python main.py
  • 此时相对路径./video/movie.mp4就会指向脚本目录下的video/movie.mp4

方法3:使用Flet的Assets资源管理(推荐,规范项目)

这是Flet推荐的资源管理方式,适合正式项目:

  1. 在项目根目录创建assets文件夹,再建video子文件夹,把MP4文件放进去,结构如下:
你的项目文件夹/
├── main.py
└── assets/
    └── video/
        └── movie.mp4
  1. 修改ft.app()的调用,指定assets目录:
ft.app(target=main, assets_dir="assets")
  1. 在VideoMedia里使用/assets/video/movie.mp4作为路径:
sample_media = [
    ft.VideoMedia(
        "/assets/video/movie.mp4",
        extras={"artist": "本地测试视频", "album": "测试专辑"}
    )
]

排查问题的小技巧

如果还是无法播放,可以检查这几点:

  • 路径是否正确:Mac系统路径区分大小写,注意文件名和文件夹名的大小写
  • 文件是否存在:手动打开路径确认文件没被移动或删除
  • 读取权限:确保当前用户有该视频文件的读取权限

修改后的完整代码示例

我帮你补充了代码里缺失的处理函数(不然运行会报错),并替换了本地路径的示例:

import random
import flet as ft
import os

def main(page: ft.Page):
    print("当前工作目录:", os.getcwd()) # 打印工作目录,方便排查路径问题
    page.theme_mode = ft.ThemeMode.LIGHT
    page.title = "TheEthicalVideo"
    page.window_always_on_top = True
    page.spacing = 20
    page.horizontal_alignment = ft.CrossAxisAlignment.CENTER

    # 补充缺失的控制函数
    def handle_stop(e):
        video.stop()
        print("Video.stop()")
    
    def handle_next(e):
        video.next()
        print("Video.next()")
    
    def handle_previous(e):
        video.previous()
        print("Video.previous()")
    
    def handle_seek(e):
        video.seek(10)
        print("Video.seek(10)")
    
    def handle_jump(e):
        video.jump_to_media(0)
        print("Jump to first media")
    
    def handle_add_media(e):
        new_media = ft.VideoMedia("./video/another_movie.mp4")
        video.playlist.append(new_media)
        video.update()
        print("Added new media")
    
    def handle_remove_media(e):
        if video.playlist:
            video.playlist.pop(random.randint(0, len(video.playlist)-1))
            video.update()
            print("Removed media")
    
    def handle_volume_change(e):
        video.volume = int(e.control.value)
        video.update()
        print(f"Volume set to {video.volume}%")
    
    def handle_playback_rate_change(e):
        video.playback_rate = e.control.value
        video.update()
        print(f"Playback rate set to {video.playback_rate}X")
    
    def handle_pause(e):
        video.pause()
        print("Video.pause()")

    def handle_play_or_pause(e):
        video.play_or_pause()
        print("Video.play_or_pause()")

    def handle_play(e):
        video.play()
        print("Video.play()")

    # 使用本地绝对路径示例(替换成你的实际路径)
    sample_media = [
        ft.VideoMedia(
            "/Users/xxx/Documents/flet_project/video/movie.mp4",
            extras={
                "artist": "本地测试视频",
                "album": "测试专辑",
            },
        ),
    ]

    # 若使用Assets方式,注释上面的sample_media,取消下面的注释并配置assets_dir
    # sample_media = [
    #     ft.VideoMedia(
    #         "/assets/video/movie.mp4",
    #         extras={
    #             "artist": "本地测试视频",
    #             "album": "测试专辑",
    #         },
    #     ),
    # ]

    page.add(
        video := ft.Video(
            expand=True,
            playlist=sample_media[0:2],
            playlist_mode=ft.PlaylistMode.LOOP,
            fill_color=ft.colors.BLUE_400,
            aspect_ratio=16/9,
            volume=100,
            autoplay=False,
            filter_quality=ft.FilterQuality.HIGH,
            muted=False,
            on_loaded=lambda e: print("Video loaded successfully!"),
            on_enter_fullscreen=lambda e: print("Video entered fullscreen!"),
            on_exit_fullscreen=lambda e: print("Video exited fullscreen!"),
        ),
        ft.Row(
            wrap=True,
            alignment=ft.MainAxisAlignment.CENTER,
            controls=[
                ft.ElevatedButton("Play", on_click=handle_play),
                ft.ElevatedButton("Pause", on_click=handle_pause),
                ft.ElevatedButton("Play Or Pause", on_click=handle_play_or_pause),
                ft.ElevatedButton("Stop", on_click=handle_stop),
                ft.ElevatedButton("Next", on_click=handle_next),
                ft.ElevatedButton("Previous", on_click=handle_previous),
                ft.ElevatedButton("Seek s=10", on_click=handle_seek),
                ft.ElevatedButton("Jump to first Media", on_click=handle_jump),
                ft.ElevatedButton("Add Random Media", on_click=handle_add_media),
                ft.ElevatedButton("Remove Random Media", on_click=handle_remove_media),
            ],
        ),
        ft.Slider(
            min=0,
            value=100,
            max=100,
            label="Volume = {value}%",
            divisions=10,
            width=400,
            on_change=handle_volume_change,
        ),
        ft.Slider(
            min=1,
            value=1,
            max=3,
            label="PlaybackRate = {value}X",
            divisions=6,
            width=400,
            on_change=handle_playback_rate_change,
        ),
    )


# 若使用Assets方式,取消下面注释并注释上面的ft.app调用
# ft.app(target=main, assets_dir="assets")
ft.app(target=main)

备注:内容来源于stack exchange,提问作者GotohRyo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.17 12:39:39