Задать вопрос
@AslanPAPA

Как сделать правильную перемотку видео в Flyleaf (wpf)?

Привет! Есть библиотека Flyleaf под капотом у неё FFmpeg, и вот я сделал для окна видеоплеера свой слайдер:
<Slider
     x:Name="positionSlider"
     Grid.Row="0"
     Margin="5,0"
     Maximum="{Binding Player.Duration}"
     Minimum="0"
     PreviewMouseLeftButtonDown="VideoSlider_PreviewMouseLeftButtonDown"
     Style="{DynamicResource VideoSliderStyle}"
     Value="{Binding Player.CurTime, Mode=TwoWay}" />


Далее в коде:
public Player player { get; set; }
 private Config playerConfig;

 private void VideoForm_Loaded(object sender, RoutedEventArgs e)
 {
     if (mediaPlayerHost != null && player == null)
     {
         try
         {
             playerConfig = new Config();
             player = new Player(playerConfig);
             mediaPlayerHost.Player = player;

             mediaPlayerHost.Player.BufferingStarted += Player_BufferingStarted;
             mediaPlayerHost.Player.BufferingCompleted += Player_BufferingCompleted;

         }
         catch (Exception ex)
         {
             MessageBox.Show($"Ошибка {ex.Message}");
         }   
     }
 }


 private void VideoForm_KeyDown(object sender, KeyEventArgs e)
 {
     if (player == null)
         return;

     string skip =
         Properties.Settings.Default.SkipTime;

     int seconds = skip switch
     {
         "5 сек" => 5,
         "10 сек" => 10,
         "15 сек" => 15,
         _ => 10
     };

     long offset = seconds * 1000L * 10000L;

     if (e.Key == Key.Right)
     {
         player.SeekForward_(offset);
     }
     else if (e.Key == Key.Left)
     {
         player.SeekBackward_(offset);
     }
 }


Но перемотка у меня плохо работает при перемотках, к примеру в коротком видео я матаю на с 10 на 20 секнуд, в коротких видео более менее всё хорошо (не всегда), а вот в больших по времени к примеру час, там я матаю с 10 до 20 секунд опять же к примеру и меня обратно на 10 перекидывает, у меня в видеоплеере есть полное время видео:
<StackPanel
     Margin="20,0,0,0"
     VerticalAlignment="Center"
     Orientation="Horizontal">


     <TextBlock Foreground="White" Text="{Binding Player.CurTime, Converter={StaticResource TicksToTime}}" />


     <TextBlock Foreground="White" Text=" / " />


     <TextBlock Foreground="White" Text="{Binding Player.Duration, Converter={StaticResource TicksToTime}}" />


 </StackPanel>


и к примеру я матаю с 10 до 20 секунд, время показывает сперва 00:20, а потом через 1 секунду опять прыгает назад к 10
как это можно исправить и сделать оптимальную перемотку?

класс Player в котором функции для перемоток:
unsafe partial class Player
{
    public bool IsOpenFileDialogOpen    { get; private set; }


    public void SeekBackward()  => SeekBackward_(Config.Player.SeekOffset);
    public void SeekBackward2() => SeekBackward_(Config.Player.SeekOffset2);
    public void SeekBackward3() => SeekBackward_(Config.Player.SeekOffset3);
    public void SeekBackward_(long offset)
    {
        if (!CanPlay)
            return;

        long seekTs = curTime - (curTime % offset) - offset;

        if (Config.Player.SeekAccurate)
            SeekAccurate(Math.Max((int) (seekTs / 10000), 0));
        else
            Seek(Math.Max((int) (seekTs / 10000), 0), false);
    }

    public void SeekForward()   => SeekForward_(Config.Player.SeekOffset);
    public void SeekForward2()  => SeekForward_(Config.Player.SeekOffset2);
    public void SeekForward3()  => SeekForward_(Config.Player.SeekOffset3);
    public void SeekForward_(long offset)
    {
        if (!CanPlay)
            return;

        long seekTs = curTime - (curTime % offset) + offset;

        if (seekTs > duration && !isLive)
            return;

        if (Config.Player.SeekAccurate)
            SeekAccurate((int)(seekTs / 10000));
        else
            Seek((int)(seekTs / 10000), true);
    }

    public void SeekToStart()   => Seek(0);
    public void SeekToEnd()     => Seek((int)((Duration / 10_000) - TimeSpan.FromSeconds(5).TotalMilliseconds));
  • Вопрос задан
  • 207 просмотров
Подписаться 3 Сложный Комментировать
Помогут разобраться в теме Все курсы
  • Нетология
    Разработчик игр на Unity
    13 месяцев
    Далее
  • Академия Эдюсон
    Разработчик игр на Unity + ИИ
    6 месяцев
    Далее
  • Stepik
    PRO C#. Профессия "Backend разработчик"
    4 месяца
    Далее
Решения вопроса 1
opium
@opium
Просто люблю качественно работать
Скорее всего не TwoWay binding виноват, а тип seek. Обычный Seek() в Flyleaf прыгает к ближайшему keyframe, а не к точной позиции. На коротких видео ключевые кадры близко — почти незаметно. В длинных GOP большой, поэтому просишь 20с, плеер показывает 20с, декодер возвращается к ближайшему keyframe на 10с.

Включи SeekAccurate в конфиге:

playerConfig.Player.SeekAccurate = true;

p.s. в SeekForward_/SeekBackward_ ещё можно убрать округление по offset — просто прибавляй stepTicks к текущей позиции напрямую.
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы