Reproduzir arquivos grandes no Windows Media Player durante o download
-
22-07-2019 - |
Pergunta
A minha pergunta é sobre a escrita de um arquivo de vídeo para o disco rígido que está sendo baixado da rede e jogá-lo ao mesmo tempo usando o Windows Media Player. O arquivo é muito grande e vai levar algum tempo para baixar. É necessário baixá-lo ao invés de apenas transmiti-lo diretamente para o Windows Media Player.
O que acontece é que, enquanto eu posso escrever para o arquivo de vídeo e lê-lo, ao mesmo tempo do meu próprio código de teste, não pode ser feito usando o Windows Media Player (pelo menos eu não percebi isso). Eu sei que é possível fazer porque a Amazon Unbox de downloads faz. Unbox permite que você jogue WMVs enquanto ele está baixando-los. E Unbox está escrito em .NET assim ...
Eu li o " C # arquivo de leitura / gravação não fileshare não aparecem para trabalhar " perguntas e respostas para a abertura de um arquivo com as bandeiras FileShare. Mas ele não está funcionando para mim. Process Monitor diz que Media Player está abrindo o arquivo com bandeiras FileShare, mas ele erros fora.
No segmento de buffer Eu tenho esse código para a leitura do arquivo da rede e escrevê-lo em um arquivo (sem tratamento de erros ou outras coisas para torná-lo mais legível):
// the download thread
void StartStreaming(Stream webStream, int bufferFullByteCount)
{
int bytesRead;
var buffer = new byte[4096];
var fileStream = new FileStream(MediaFile.FullName, FileMode.Create, FileAccess.Write, FileShare.ReadWrite);
var writer = new BinaryWriter(fileStream);
var totalBytesRead = 0;
do
{
bytesRead = webStream.Read(buffer, 0, 4096);
if (bytesRead != 0)
{
writer.Write(buffer, 0, (int)bytesRead);
writer.Flush();
totalBytesRead += bytesRead;
}
if (totalBytesRead >= bufferFullByteCount)
{
// fire an event to a different thread to tell
// Windows Media Player to start playing
OnBufferingComplete(this, new BufferingCompleteEventArgs(this, MediaFile));
}
} while (bytesRead != 0);
}
Este parece funcionar bem. O arquivo grava no disco e tem as permissões corretas.
Mas então aqui está o manipulador de eventos no outro segmento para reproduzir o vídeo
// the playback thread
private void OnBufferingComplete(object sender, BufferingCompleteEventArgs e)
{
axWindowsMediaPlayer1.URL = e.MediaFile.FullName;
}
Windows Media Player indica que sua criação do ficheiro e, em seguida, simplesmente pára com um erro que o arquivo não pode ser aberto "já abriu em outro processo."
Eu tentei tudo que eu posso pensar. o que estou perdendo? Se os caras da Amazon pode fazer isso, então eu também posso, certo?
edit: esse código funciona com o MPlayer, VLC, e Media Player Classic; apenas não o Windows Media Player ou Windows Media Player Center. IOW, os únicos jogadores que eu precisar deles para trabalhar. ugh!
edit2: Eu fui tão longe para usar MiniHttp para transmitir o vídeo para o Windows Media Player para ver se que "enganar" WMP em jogar um vídeo que está sendo download. Nada a fazer. Enquanto WMP fez aberto o arquivo, ele esperou até que o arquivo mpeg foi completamente copiado antes que ele começou a tocar. Como ele sabe?
edit3: Depois de algumas escavações eu descobri o problema. Eu estou trabalhando com arquivos MPEG2. O problema não é necessariamente com o Windows Media Player, mas com a Microsoft MPEG2 DirectShow Splitter que WMP usa para abrir os arquivos MPEG2 que estou tentando jogar e baixar ao mesmo tempo. O Splitter abre os arquivos no modo não-Shared. Não é assim com arquivos WMV. WMP abre-los no modo e tudo funciona compartilhados como esperado.
Solução
Decidi responder a minha própria pergunta no caso de alguém corre para esta situação rara.
A resposta curta é esta:. Windows Media Player (como esta escrito) permitirá que um arquivo a ser baixado e jogar ao mesmo tempo, enquanto que a funcionalidade é apoiado por CODECS envolvidos na prestação do arquivo
Para citar a última edição para a pergunta:
Depois de algumas escavações eu descobri o problema. Eu estou trabalhando com arquivos MPEG2. O problema não é necessariamente com o Windows Media Player, mas com a Microsoft MPEG2 DirectShow Splitter que WMP usa para abrir os arquivos MPEG2 que estou tentando jogar e baixar ao mesmo tempo. O Splitter abre os arquivos no modo não-Shared. Não é assim com arquivos WMV. WMP abre-los no modo e tudo funciona compartilhados como esperado.
Outras dicas
Quando você abre o arquivo para escrever você não deve usar FileShare.ReadWrite. em vez disso você deve usar FileShare.Read:
var fileStream = new FileStream(
MediaFile.FullName, FileMode.Create, FileAccess.Write, FileShare.Read);
Quando mplayer.exe processar abrir o arquivo para leitura vai primeiro tentar abri-lo com FileShare.Read que irá falhar mas, em seguida, vai tente novamente com FileShare.ReadWrite que terá sucesso.
Updated 16 de março depois de comentário por @darin:
Você está especificando FileShare.ReadWrite
quando você está escrevendo o arquivo, o que teoricamente permite que outro processo para abri-lo para escrever também.
Tente alterar o seu código apenas FileShare.Read
pedido:
var fileStream
= new FileStream(
MediaFile.FullName,
FileMode.Create,
FileAccess.Write,
FileShare.Read); // Instead of ReadWrite
Para citar MSDN :
FileShare.Read: Permite posterior abertura do arquivo para leitura.
FileShare.ReadWrite: Permite posterior abertura do arquivo para leitura ou escrita.