Playing and downloading streaming media in iOS
Introduction to streaming media in iOS: A stream playing mode between downloading local playback and Real-Time Streaming Media. Downloading local playback must download all files before playing, incremental download does not have to wait until all the downloads are completed before playing the video. It can download and play the video. After the video content is completed, the entire file will be saved on the mobile phone.
Real-Time Streaming Media
Real-Time Streaming Media receives data packets while playing the video. Local files are not retained. Real-Time Streaming is always transmitted in real time and can be broadcast in real time, supporting random access, users can quickly forward or return to view the content in front or back. Real-Time Streaming Media transmission must ensure that the data packet transmission speed is greater than the file playback speed. Otherwise, the video you see will be paused. When the network is congested, the quality of the video will decrease, so it is better to ensure that the quality of the video can be downloaded gradually.
The following is a self-tested streaming media playback and download Tutorial:
1. Build the interface ()
2. Third-Party assistant classes used
: Http://pan.baidu.com/s/1hrvqXA8
3. Start the project-header files and related macros
LO_ViewController.h
#import
#import
#import "M3U8Handler.h"#import "VideoDownloader.h"#import "HTTPServer.h"@interface LO_ViewController : UIViewController
@property (nonatomic, strong)HTTPServer * httpServer;@property (nonatomic, strong)VideoDownloader *downloader;@end
LO_ViewController.m
# Import "plugin" @ interface LO_ViewController () @ property (weak, nonatomic) IBOutlet UIProgressView * progressView; @ property (weak, nonatomic) IBOutlet UILabel * progressLabel; @ property (weak, nonatomic) IBOutlet UIButton * downloadButton; @ property (weak, nonatomic) IBOutlet UIButton * clearButton; @ end @ implementation LO_ViewController-(void) viewDidLoad {[super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. // open the local server [self openHttpServer]; if ([[[NSUserDefaults standardUserDefaults] objectForKey: @ "isDownload"] boolValue]) {[self. downloadButton setTitle: @ "completed" forState: UIControlStateNormal]; self. downloadButton. enabled = NO; self. clearButton. enabled = YES; M3U8Handler * handler = [[M3U8Handler alloc] init]; [handler praseUrl: [NSString stringWithFormat: @ "http://v.youku.com/player/getM3U8/vid/XNjUxMTE4NDAw/type/mp4"]; handler. playlist. uuid = @ "XNjUxMTE4NDAw"; self. downloader = [[VideoDownloader alloc] initWithM3U8List: handler. playlist]; [self. downloader addObserver: self forKeyPath: @ "javasaches" options: NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context: nil]; // judge whether to clear the cache }}
# Pragma mark-open the local server
-(Void) openHttpServer {self. httpServer = [[HTTPServer alloc] init]; [self. httpServer setType: @ "_ http. _ tcp. "]; // set the service type [self. httpServer setPort: 12345]; // set the server port // obtain the downloads path NSString * webPath = [kLibraryCache stringByAppendingPathComponent: kPathDownload] under the local Library/Cache path; NSLog (@ "------------- \ nSetting document root: % @ \ n", webPath); // set the server path [self. httpServer setDocumentRoot: webPath]; AUC Rror * error; if (! [Self. httpServer start: & error]) {NSLog (@ "------------- \ nError starting HTTP Server: % @ \ n", error );}}
# Pragma mark-clear cache-(IBAction) Prepare aches :( id) sender {[self. downloader cleanDownloadFiles];}
# Pragma mark-online streaming media playback
-(IBAction) playStreamingMedia :( id) sender {// youku video m3u8 new address format: http://pl.youku.com/playlist/m3u8? Vid = XNjUxMTE4NDAw & type = mp4 // if the above link is unavailable, use this link. // if neither of the above two formats works, use this format, of course, if this format is not good, Is the above, or directly change the corresponding m3u8 address http://pl.youku.com/playlist/m3u8? Vid = 162779600 & ts = 1407469897 & ctype = 12 & token = 3357 & keyframe = 1 & sid = 640746989782612d6cc70 & ev = 1 & type = mp4 & ep = 426% 2B24 & oip = 2043219268 NSURL * url = [[NSURL alloc] initWithString: @ "http://pl.youku.com/playlist/m3u8? Vid = 162779600 & ts = 1407469897 & ctype = 12 & token = 3357 & keyframe = 1 & sid = 640746989782612d6cc70 & ev = 1 & type = flv & ep = %% 2B24 & oip = 2043219268 "]; MPMoviePlayerViewController * player = [[MPMoviePlayerViewController alloc] initWithContentURL: url]; [self presentMoviePlayerViewControllerAnimated: player];}
# Pragma mark-video download
-(IBAction) downloadStreamingMedia :( id) sender {UIButton * downloadButton = sender; // obtain the local Library/Cache path NSString * localDownloadsPath = [kLibraryCache stringByAppendingPathComponent: kPathDownload]; // obtain the local video path NSString * filePath = [localDownloadsPath stringByAppendingPathComponent: @ "XNjUxMTE4NDAw/movie. m3u8 "]; NSFileManager * fileManager = [NSFileManager defaultManager]; // determines whether the video is cached. If yes, the local cache is played. F ([fileManager fileExistsAtPath: filePath]) {[downloadButton setTitle: @ "completed" forState: UIControlStateNormal]; downloadButton. enabled = NO;} else {M3U8Handler * handler = [[M3U8Handler alloc] init]; handler. delegate = self; // parse m3u8 video address [handler praseUrl: @ "http://pl.youku.com/playlist/m3u8? Vid = 162779600 & ts = 1407469897 & ctype = 12 & token = 3357 & keyframe = 1 & sid = 640746989782612d6cc70 & ev = 1 & type = flv & ep = %% 2B24 & oip = 2043219268 "]; // enable the network indicator [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible: YES];}
# Pragma mark-play a locally cached video
-(IBAction) playVideoFromLocal :( id) sender {NSString * playurl = [NSString stringWithFormat: @ "http: // 127.0.0.1: 12345/XNjUxMTE4NDAw/movie. m3u8 "]; NSLog (@" local video address ----- % @ ", playurl); // obtain the local Library/Cache path NSString * localDownloadsPath = [kLibraryCache stringByAppendingPathComponent: kPathDownload]; // obtain the local video path NSString * filePath = [localDownloadsPath stringByAppendingPathComponent: @ "XNjUxMTE4NDAw/movie. m3u8 "]; NSFileManager * fileManager = [NSFileManager defaultManager]; // determines whether the video is cached. if yes, the local cache is played if ([fileManager fileExistsAtPath: filePath]) {MPMoviePlayerViewController * playerViewController = [[MPMoviePlayerViewController alloc] initWithContentURL: [NSURL URLWithString: playurl]; [self preview: playerViewController];} else {UIAlertView * alertView = [[UIAlertView alloc] initWithTitle: @ "Sorry" message: @ "current video not cached" delegate: self cancelButtonTitle: @ "OK" otherButtonTitles: nil, nil]; [alertView show] ;}# pragma mark-# pragma mark-video resolution completed-(void) praseM3U8Finished :( M3U8Handler *) handler {handler. playlist. uuid = @ "XNjUxMTE4NDAw"; self. downloader = [[VideoDownloader alloc] initWithM3U8List: handler. playlist]; [self. downloader addObserver: self forKeyPath: @ "currentProgress" options: NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context: nil]; // set the observer to get the current download progress [self. downloader addObserver: self forKeyPath: @ "javasaches" options: NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context: nil]; // determines whether to clear the cache self. downloader. delegate = self; [self. downloader startDownloadVideo]; // start download}
# Pragma mark-monitor the download progress display/cache cleanup through the observer
-(Void) observeValueForKeyPath :( NSString *) keyPath ofObject :( id) object change :( NSDictionary *) change context :( void *) context {if ([keyPath isEqualToString: @ "clearCaches"]) {self. downloadButton. enabled = YES; [self. downloadButton setTitle: @ "Download" forState: UIControlStateNormal]; self. clearButton. enabled = NO; [[NSUserDefaults standardUserDefaults] setObject: [NSNumber numberWithBool: NO] forKey: @ "isDownload"]; [[NSUserDefaults standardUserDefaults] synchronize]; self. progressView. progress = 0.0; self. progressLabel. text = [NSString stringWithFormat: @ "%. 2f % ", 0.0];} else {self. progressLabel. text = [NSString stringWithFormat: @ "%. 2f % ", 100 * [[change objectForKey: @" new "] floatValue]; self. progressView. progress = [[change objectForKey: @ "new"] floatValue]; if (self. progressView. progress = 1) {[[NSUserDefaults standardUserDefaults] setObject: [NSNumber numberWithBool: YES] forKey: @ "isDownload"]; [self. downloadButton setTitle: @ "completed" forState: UIControlStateNormal]; [[NSUserDefaults standardUserDefaults] synchronize]; self. clearButton. enabled = YES; self. downloadButton. enabled = NO ;}}}
# Pragma mark-video resolution failure-(void) praseM3U8Failed :( M3U8Handler *) handler {NSLog (@ "video resolution failed-failed -- % @", handler ); UIAlertView * alertView = [[UIAlertView alloc] initWithTitle: @ "OH, NO ~