Онлайн воспроизведение видео из torrent файлов
Я знаю, что есть, такие плееры, как vlc, rox, которые могут онлайн воспроизводить видео из torrent файлов по мере их скачивания, но я не знаю, как реализовать это на xamarin C#. Я не знаю, можно ли это реализовать с помощью плагинов, или можно обойтись обычным плеером. (простите, я не мастер задавать вопросы... но может кто-нибудь может помочь мне...)
Ответы (1 шт):
Ну, задача вполне простая, правда я могу накосячить с тонкостями Xamarin (ибо не знаю его), но он очень похож на WPF, поэтому я буду делать на нем.
И так, вам нужно две вещи:
- Торрент клиент. На C# один из самых популярных и функциональных, это MonoTorrent.
- Вам нужен плеер, который умеет либо работать со
Stream, либо уметь буферно считывать файл. Вот тут я без понятия что у вас там на Xamarin, может есть готовое решение, а может, будете использовать как я, VLC.
Так, с этим разобрались, теперь код:
Качаем с NuGet нужные пакеты (я для WPF возьму
MonoTorrent,Vlc.DotNet.Wpf(контрол для WPF XAML),VideoLAN.LibVLC.Windows(сам плеер).Создадим в проекте отдельный
UserControl, будет некой оберткой над плеером.В XAML пишем просто
<Vlc:VlcControl x:Name="media"/>В C# коде пишем нечто такое:
public partial class VLCPlayer : UserControl { public VLCPlayer() => InitializeComponent(); private void UserControl_Loaded(object sender, RoutedEventArgs e) { var vlcLibDirectory = new DirectoryInfo(Path.Combine(AppContext.BaseDirectory, "libvlc", IntPtr.Size == 4 ? "win-x86" : "win-x64")); media.SourceProvider.CreatePlayer(vlcLibDirectory); } public Stream Stream { get => (Stream)GetValue(StreamProperty); set => SetValue(StreamProperty, value); } public static readonly DependencyProperty StreamProperty = DependencyProperty.Register("Stream", typeof(Stream), typeof(VLCPlayer), new FrameworkPropertyMetadata(null, new PropertyChangedCallback(OnFirstPropertyChanged))); private static void OnFirstPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { var player = d as VLCPlayer; if (player is not null) player.Play(); } private void Play() { media.SourceProvider.MediaPlayer.Play(Stream); } }
Здесь мы инициализируем плеер (как сказано в документации), а также делаем
DependencyProperty, которое будем пробрасывать намStreamи в случае его изменения, запускать плеер.Далее следаем отдельный класс, который будем содержать в себе свойства для привязки, да и запустит весь процесс:
public class MainViewModel : BindingBase { private Stream stream; public Stream Stream { get => stream; set => SetProperty(ref stream, value); } private string name; public string Name { get => name; set => SetProperty(ref name, value); } private double progress; public double Progress { get => progress; set => SetProperty(ref progress, value); } private TorrentState state; public TorrentState State { get => state; set => SetProperty(ref state, value); } public async Task StartDownload() { var engine = new ClientEngine(); var torrent = await Torrent.LoadAsync("D:\\test.torrent"); var manager = await engine.AddStreamingAsync(torrent, "Downloads"); await manager.StartAsync(); await manager.WaitForMetadataAsync(); var task = Task.Run(() => { Name = manager.Torrent.Name; while (engine.IsRunning) { Progress = manager.Progress; State = manager.State; } }); var file = manager.Files[0]; var stream = await manager.StreamProvider.CreateStreamAsync(file, CancellationToken.None); Stream = stream; await Task.WhenAll(task); } }
BindingBase - это реализация INotifyPropertyChanged, чтоб свойства наши обновлялись, вопрос не про правильность реализации, а вообще про сам принцип, поэтому я MVVM и прочее здесь опущу.
В StartDownload мы инициализируем клиент торрента, добавляем в него наш торрент файл (или что там у вас будет) как Streaming, это позволит ему качать куски поочередно. await manager.WaitForMetadataAsync(); - ожидает получения метаданных торрента, без него получение Stream может выдать ошибку, ибо файла еще может не быть! Для наглядности я сделал task, который будет выводить нам информацию на экран (статус, название файла, прогресс), ну и самое тут главное, это stream - мы получаем Stream первого файла в торренте, который качаем и отдаем его нашему плееру.
В XAML окна делаем самую простейшую разметку:
<Grid> <Grid.RowDefinitions> <RowDefinition Height="Auto"/> <RowDefinition/> <RowDefinition Height="Auto"/> </Grid.RowDefinitions> <StackPanel Orientation="Horizontal" Margin="10 5"> <TextBlock Text="{Binding State, StringFormat={}[{0}]}"/> <TextBlock Text="{Binding Name}" FontWeight="Medium" Margin="5 0"/> <Grid> <ProgressBar Value="{Binding Progress}"/> <TextBlock Text="{Binding Progress, StringFormat={}{0:0.00}%}" Margin="5 0"/> </Grid> </StackPanel> <local:VLCPlayer Grid.Row="1" Stream="{Binding Stream}"/> <Button Grid.Row="2" Content="Start" Click="Button_Click"/> </Grid>А, ну и по клику кнопки нам надо лишь вызвать
StartDownload().Не забудьте еще задать
DataContext(или что у вас там на Xamarin, название чуть может отличаться).
Запускаем, смотрим:
Я из гифки многое вырезал (там просто черный экран и бегут проценты), но результат думаю можно увидеть. Заметьте, что воспроизведение началось только тогда, когда файл немного скачался (у меня это 6%). Я думаю, можно будет поиграться с настройками и изменить этот показатель.
И так, давайте поговорим о недочетах в моем примере:
- Все в одной куче, не стоит так делать!
Button_Click- не используйте контролы из кода и наоборот, старайтесь максимально отвязывать их. За клики отвечаетICommand.CancellationToken.None- сделайте токен отмены, а не глушите его как я, этот токен поместите во все async задачи. Так вы будете иметь контроль над процессом, сможете его остановить.Task.Run- не уверен в этой конструкции... Скорей всего она нужна, но код, который внутри, лучше переделать наIProgress. Увы,MonoTorrentне дает нам событий, которые отдавали бы прогресс.- Как я говорил выше, воспроизведение начинается примерно на 6% (у меня это минута ожидания), это надо анализировать и исправлять, хотя я торрент просмотрами не занимаюсь, может такая длинная пауза и норма.
Streamследует закрыть после завершения его использования.
Собственно, вот вам и просмотр торрентов на языке C#, адаптировать думаю сможете под Xamarin, главное найдите плеер (в NuGet есть тот же VLC для Xamarin от разных авторов)!
