首页 > 代码库 > M3U8Downloader

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 }

 

M3U8Downloader