Diffuser de la vidéo pendant le téléchargement iOS

Je suis en utilisant iOS 7 et j'ai un .mp4 vidéo que j'ai besoin de télécharger dans mon application. La vidéo est importante (environ 1 GO) c'est pourquoi il n'est pas inclus dans le cadre de l'application. Je veux que l'utilisateur soit en mesure de commencer à regarder la vidéo dès que commence le téléchargement. Je veux aussi la vidéo pour pouvoir être mis en cache sur l'appareil iOS, de sorte que l'utilisateur n'a pas besoin de le télécharger à nouveau plus tard. À la fois les méthodes normales de la lecture de vidéos (téléchargement progressif et la diffusion en direct) ne semblent pas laisser de la cache de la vidéo, j'ai donc fait mon propre service web que les morceaux de mon fichier vidéo et le flux d'octets vers le client. J'ai commencer le streaming HTTP appel à l'aide de NSURLConnection:

self.request = [[NSMutableURLRequest alloc] initWithURL:self.url];
[self.request setTimeoutInterval:10]; //Expect data at least every 10 seconds
[self.request setHTTPMethod:@"GET"];
self.connection = [[NSURLConnection alloc] initWithRequest:self.request delegate:self startImmediately:YES];

Lorsque je reçois un segment de données, je l'ajouter à la fin de la copie locale du fichier:

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
     NSFileHandle *handle = [NSFileHandle fileHandleForWritingAtPath:[self videoFilePath]];
     [handle truncateFileAtOffset:[handle seekToEndOfFile]];
     [handle writeData:data];
}

Si je laisse l'appareil exécuté, le fichier est téléchargé avec succès et je peux lire à l'aide d'MPMoviePlayerViewController:

NSURL *url=[NSURL fileURLWithPath:self.videoFilePath];
MPMoviePlayerViewController *controller = [[MPMoviePlayerViewController alloc] initWithContentURL:url];
controller.moviePlayer.scalingMode = MPMovieScalingModeAspectFit;
[self presentMoviePlayerViewControllerAnimated:controller];

Cependant, si je commence le joueur avant que le fichier est téléchargé complètement, la vidéo commence à jouer très bien. Il a même la bonne longueur de la vidéo affichée en haut barre de défilement. Mais quand l'utilisateur arrive à la position dans la vidéo que j'avais terminé le téléchargement avant de lancé la vidéo, la vidéo se bloque. Si j'ai fermer et rouvrir le MPMoviePlayerViewController, puis la vidéo, jusqu'à ce qu'il arrive à l'emplacement que j'étais alors à quand j'ai lancé le MPMoviePlayerViewController de nouveau. Si j'attends jusqu'à ce que l'intégralité de la vidéo est téléchargée, la vidéo est lue sans problème.

Je ne reçois pas les événements déclenchés, ou des messages d'erreur affichés dans la console lorsque cela se produit (MPMoviePlayerPlaybackStateDidChangenotification et MPMoviePlayerPlaybackDidFinishNotification ne sont jamais envoyés après la vidéo commence). Il semble qu'il y est autre chose, c'est de dire que le contrôleur de ce que la longueur de la vidéo est autre que ce que le pointeur est à l'aide de...

Personne ne sait ce qui pourrait être à l'origine de ce problème? Je ne suis pas lié à l'utilisation de MPMoviePlayerViewController, donc si une autre vidéo de la lecture de la méthode de travail dans cette situation, je suis tout à fait pour.

Liées À Des Questions Non Résolues:

AVPlayer et Progressive des Téléchargements de Vidéo avec AVURLAssets

Progressive de Téléchargement de Vidéo sur iOS

Comment jouer une progression du téléchargement du fichier vidéo dans IOS

Mise à JOUR de 1
J'ai trouvé que la vidéo de décrochage est en effet en raison de la taille du fichier de la vidéo commence à jouer. Je peux contourner ce problème en créant un zéro-ed fichier avant de commencer le téléchargement et sur l'écraser comme je l'aller. Depuis que j'ai le contrôle sur le serveur vidéo en continu, j'ai ajouté un en-tête personnalisé donc je sais que la taille du fichier est transmis (par défaut la taille du fichier d'en-tête d'un fichier de transmission en continu est de -1). Je suis entrain de créer le fichier dans mon didReceiveResponse méthode comme suit:

- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{        
    //Retrieve the size of the file being streamed.
    NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
    NSDictionary *headers = httpResponse.allHeaderFields;

    NSNumberFormatter * formatter = [[NSNumberFormatter alloc] init];
    [formatter setNumberStyle:NSNumberFormatterDecimalStyle];
    self.streamingFileSize = [formatter numberFromString:[headers objectForKey:@"StreamingFileSize"]];

    //Check if we need to initialize the download file
    if (![[NSFileManager defaultManager] fileExistsAtPath:self.path])
    {            
        //Create the file being downloaded
        [[NSData data] writeToFile:self.path atomically:YES];

        //Allocate the size of the file we are going to download.
        const char *cString = [self.path cStringUsingEncoding:NSASCIIStringEncoding];
        int success = truncate(cString, self.streamingFileSize.longLongValue);
        if (success != 0)
        {
            /* TODO: handle errors here. Probably not enough space... See 'man truncate' */
        }
    }
}

Cela fonctionne très bien, sauf que tronquer entraîne l'application à bloquer pendant environ 10 secondes et il crée l' ~1 GO de fichiers sur le disque (sur le simulateur, il est instantanée, que d'un véritable dispositif a ce problème). C'est là que je suis coincé maintenant personne ne sait de façon à allouer un fichier de manière plus efficace, ou une autre méthode pour obtenir le lecteur vidéo de reconnaître la taille du fichier sans avoir besoin de réellement les attribuer? Je sais que certains systèmes de fichiers de support "taille du fichier" et "taille sur le disque" comme deux propriétés différentes... ne sais pas si iOS a quelque chose comme ça?

  • ne pourrais pas travailler avec moi
InformationsquelleAutor lehn0058 | 2014-01-03