M3U8Downloader

  1 import java.io.BufferedReader;
  2 import java.io.File;
  3 import java.io.FileInputStream;
  4 import java.io.FileOutputStream;
  5 import java.io.IOException;
  6 import java.io.InputStreamReader;
  7 import java.net.URL;
  8 import java.util.ArrayList;
  9 import java.util.List;
 10 import java.util.concurrent.ExecutorService;
 11 import java.util.concurrent.Executors;
 12
 13 import org.apache.commons.io.IOUtils;
 14
 15 public class M3U8Downloader {
 16
 17     static String url = "http://ftp.luplayer.com/20161103/mo93Hc9o/index.m3u8";
 18     static String tofile = "/Users/jieyuefeng/Dev/output/20170210/Movie.ts";
 19
 20     public static void main(String[] args) throws IOException, InterruptedException {
 21
 22         System.out.println("get index for: " + url);
 23
 24         M3U8 m3u8 = parseIndex(url);
 25
 26         float f = 0;
 27         for (M3U8Ts ts : m3u8.getTsList()) {
 28             f += ts.getSeconds();
 29         }
 30         System.out.println("movie length: " + ((int) f / 60) + "min" + (int) f % 60 + "sec");
 31
 32         download(m3u8, tofile);
 33
 34         executor.shutdown();
 35         System.out.println("Wait for downloader...");
 36         while (!executor.isTerminated()) {
 37             Thread.sleep(100);
 38         }
 39
 40         merge(m3u8, tofile);
 41
 42         System.out.println("download completed for: " + tofile);
 43     }
 44
 45     public static void merge(M3U8 m3u8, String tofile) throws IOException {
 46         File file = new File(tofile);
 47         FileOutputStream fos = new FileOutputStream(file);
 48         for (M3U8Ts ts : m3u8.getTsList()) {
 49             IOUtils.copyLarge(new FileInputStream(new File(file.getParentFile(), ts.getFile())), fos);
 50         }
 51         fos.close();
 52     }
 53
 54     private static ExecutorService executor = Executors.newFixedThreadPool(10);
 55
 56     public static void download(final M3U8 m3u8, final String tofile) throws IOException {
 57         final File dir = new File(tofile).getParentFile();
 58         if (!dir.exists()) {
 59             dir.mkdirs();
 60         } else if (dir.list().length > 0) {
 61             throw new IOException("tofile dir must be empty or not exists");
 62         }
 63
 64         for (final M3U8Ts ts : m3u8.getTsList()) {
 65             executor.execute(new Runnable() {
 66
 67                 @Override
 68                 public void run() {
 69                     try {
 70                         System.out.println(
 71                                 "download " + (m3u8.getTsList().indexOf(ts) + 1) + "/" + m3u8.getTsList().size() + ": " + ts);
 72                         FileOutputStream writer = new FileOutputStream(new File(dir, ts.getFile()));
 73                         IOUtils.copyLarge(new URL(m3u8.getBasepath() + ts.getFile()).openStream(), writer);
 74                         writer.close();
 75                         System.out.println("download ok for: " + ts);
 76                     } catch (IOException e) {
 77                         e.printStackTrace();
 78                     }
 79
 80                 }
 81             });
 82
 83         }
 84
 85     }
 86
 87     static M3U8 parseIndex(String url) throws IOException {
 88
 89         BufferedReader reader = new BufferedReader(new InputStreamReader(new URL(url).openStream()));
 90
 91         String basepath = url.substring(0, url.lastIndexOf("/") + 1);
 92
 93         M3U8 ret = new M3U8();
 94         ret.setBasepath(basepath);
 95
 96         String line;
 97         float seconds = 0;
 98         while ((line = reader.readLine()) != null) {
 99             if (line.startsWith("#")) {
100                 if (line.startsWith("#EXTINF:")) {
101                     line = line.substring(8);
102                     if (line.endsWith(",")) {
103                         line = line.substring(0, line.length() - 1);
104                     }
105                     seconds = Float.parseFloat(line);
106                 }
107                 continue;
108             }
109             if (line.endsWith("m3u8")) {
110                 return parseIndex(basepath + line);
111             }
112             ret.addTs(new M3U8Ts(line, seconds));
113             seconds = 0;
114         }
115         reader.close();
116
117         return ret;
118     }
119
120     static class M3U8 {
121         private String basepath;
122         private List<M3U8Ts> tsList = new ArrayList<M3U8Ts>();
123
124         public String getBasepath() {
125             return basepath;
126         }
127
128         public void setBasepath(String basepath) {
129             this.basepath = basepath;
130         }
131
132         public List<M3U8Ts> getTsList() {
133             return tsList;
134         }
135
136         public void setTsList(List<M3U8Ts> tsList) {
137             this.tsList = tsList;
138         }
139
140         public void addTs(M3U8Ts ts) {
141             this.tsList.add(ts);
142         }
143
144         @Override
145         public String toString() {
146             StringBuilder sb = new StringBuilder();
147             sb.append("basepath: " + basepath);
148             for (M3U8Ts ts : tsList) {
149                 sb.append("\nts: " + ts);
150             }
151
152             return sb.toString();
153         }
154
155     }
156
157     static class M3U8Ts {
158         private String file;
159         private float seconds;
160
161         public M3U8Ts(String file, float seconds) {
162             this.file = file;
163             this.seconds = seconds;
164         }
165
166         public String getFile() {
167             return file;
168         }
169
170         public void setFile(String file) {
171             this.file = file;
172         }
173
174         public float getSeconds() {
175             return seconds;
176         }
177
178         public void setSeconds(float seconds) {
179             this.seconds = seconds;
180         }
181
182         @Override
183         public String toString() {
184             return file + " (" + seconds + "sec)";
185         }
186
187     }
188
189 }
时间: 2024-11-09 06:13:28

M3U8Downloader的相关文章

【转】HLS视频点播&amp;直播初探

特别提示:本人博客部分有参考网络其他博客,但均是本人亲手编写过并验证通过.如发现博客有错误,请及时提出以免误导其他人,谢谢!欢迎转载,但记得标明文章出处:http://www.cnblogs.com/mao2080/ 前端可选的视频直播协议大致只有两种: RTMP(Real Time Messaging Protocol) HLS(HTTP Live Streaming) 其中RTMP是Adobe开发的协议,无法在iPhone中兼容,故目前兼容最好的就是HLS协议了. HTTP Live Str

HLS视频点播&amp;直播初探

前端可选的视频直播协议大致只有两种: RTMP(Real Time Messaging Protocol) HLS(HTTP Live Streaming) 其中RTMP是Adobe开发的协议,无法在iPhone中兼容,故目前兼容最好的就是HLS协议了. HTTP Live Streaming(HLS)是苹果公司实现的基于HTTP的流媒体传输协议,可实现流媒体的直播和点播.原理上是将视频流分片成一系列HTTP下载文件.所以,HLS比RTMP有较高的延迟. 前端播放HLS Native支持 And