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

Python 3.10媒体播放器:AB循环与调速按钮失效及格式支持需求

问题解决:Kivy媒体播放器AB循环与速度调节失效及格式支持扩展

一、功能失效问题修复

1. 播放速度滑块失效修复

Kivy的VideoPlayer是容器组件,实际播放核心是内部的video属性,直接设置self.video.playback_rate不会生效,需访问内部视频对象:

修改set_speed方法:

def set_speed(self, instance, value):
    # 确保视频组件已初始化
    if hasattr(self.video, 'video') and self.video.video:
        self.video.video.playback_rate = value
        # 更新速度显示文本
        self.speed_label.text = f'Speed: {round(value, 2)}x'

2. AB循环功能失效修复

原逻辑判断条件有误,且未校验A点时间早于B点,导致循环异常。调整set_a、set_b和on_update方法:

修改set_a和set_b方法:

def set_a(self, instance):
    if self.video.source and self.video.position >= 0:
        self.a_time = self.video.position
        print(f'Set A at {round(self.a_time, 2)}s')

def set_b(self, instance):
    if self.video.source and self.video.position >= 0:
        self.b_time = self.video.position
        print(f'Set B at {round(self.b_time, 2)}s')

修改on_update方法:

def on_update(self, dt):
    if self.loop_enabled and self.a_time is not None and self.b_time is not None:
        # 确保A点早于B点,否则关闭循环并提示
        if self.a_time >= self.b_time:
            print('A time must be earlier than B time!')
            self.loop_enabled = False
            return
        # 播放到B点后跳回A点
        if self.video.position >= self.b_time:
            self.video.position = self.a_time

二、扩展视频格式支持

Kivy视频播放依赖FFmpeg,默认支持格式有限,安装官方FFmpeg依赖包即可支持MP4、MKV、AVI、MOV等主流格式:

执行命令安装:

pip install kivy-deps.ffmpeg

完整修改后的代码

import kivy
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.button import Button
from kivy.uix.label import Label
from kivy.uix.slider import Slider
from kivy.uix.filechooser import FileChooserListView
from kivy.uix.popup import Popup
from kivy.uix.videoplayer import VideoPlayer

kivy.require('2.0.0')

class MediaPlayer(BoxLayout):
    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        self.orientation = 'vertical'

        self.video = VideoPlayer(source='', state='stop')
        self.add_widget(self.video)

        self.controls = BoxLayout(size_hint_y=None, height='50dp')
        self.add_widget(self.controls)

        self.play_button = Button(text='Play/Pause')
        self.play_button.bind(on_press=self.toggle_play)
        self.controls.add_widget(self.play_button)

        self.a_button = Button(text='Set A')
        self.a_button.bind(on_press=self.set_a)
        self.controls.add_widget(self.a_button)

        self.b_button = Button(text='Set B')
        self.b_button.bind(on_press=self.set_b)
        self.controls.add_widget(self.b_button)

        self.loop_button = Button(text='Toggle Loop')
        self.loop_button.bind(on_press=self.toggle_loop)
        self.controls.add_widget(self.loop_button)

        self.speed_label = Label(text='Speed: 1.0x')
        self.controls.add_widget(self.speed_label)

        self.speed_slider = Slider(min=0.4, max=1.2, value=1.0)
        self.speed_slider.bind(value=self.set_speed)
        self.controls.add_widget(self.speed_slider)

        self.browse_button = Button(text='Browse')
        self.browse_button.bind(on_press=self.browse_file)
        self.controls.add_widget(self.browse_button)

        self.a_time = None
        self.b_time = None
        self.loop_enabled = False

    def toggle_play(self, instance):
        if self.video.state == 'play':
            self.video.state = 'pause'
        else:
            self.video.state = 'play'

    def set_a(self, instance):
        if self.video.source and self.video.position >= 0:
            self.a_time = self.video.position
            print(f'Set A at {round(self.a_time, 2)}s')

    def set_b(self, instance):
        if self.video.source and self.video.position >= 0:
            self.b_time = self.video.position
            print(f'Set B at {round(self.b_time, 2)}s')

    def toggle_loop(self, instance):
        self.loop_enabled = not self.loop_enabled
        print(f'Loop enabled: {self.loop_enabled}')

    def set_speed(self, instance, value):
        if hasattr(self.video, 'video') and self.video.video:
            self.video.video.playback_rate = value
            self.speed_label.text = f'Speed: {round(value, 2)}x'

    def browse_file(self, instance):
        content = BoxLayout(orientation='vertical')
        filechooser = FileChooserListView()
        content.add_widget(filechooser)

        select_button = Button(text='Select')
        content.add_widget(select_button)

        popup = Popup(title='Select a video file', content=content, size_hint=(0.9, 0.9))

        def on_file_select(instance):
            if filechooser.selection:
                self.video.source = filechooser.selection[0]
                self.video.state = 'play'
                popup.dismiss()

        select_button.bind(on_press=on_file_select)
        popup.open()

    def on_update(self, dt):
        if self.loop_enabled and self.a_time is not None and self.b_time is not None:
            if self.a_time >= self.b_time:
                print('A time must be earlier than B time!')
                self.loop_enabled = False
                return
            if self.video.position >= self.b_time:
                self.video.position = self.a_time

class MediaPlayerApp(App):
    def build(self):
        player = MediaPlayer()
        kivy.clock.Clock.schedule_interval(player.on_update, 1 / 30.0)
        return player

if __name__ == '__main__':
    MediaPlayerApp().run()

内容的提问来源于stack exchange,提问作者newGIS

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 18:40:15