根据M3U8地址下载视频

       下面展示的是通过M3U8地址,把这个地址转为一个视频文件;只是一个基本案例,当然,有些下载的M3U8文件里面格式是不一样的,还有的是加过密的,道理都是一个道理。

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import org.apache.commons.io.IOUtils;
 
/**
 * 根据M3U8地址下载视频
 * IOUtils.copyLarge 需要引入commons.io包
 * 
 * java.version 1.7
 */
public class M3U8Downloader {
 
    /** m3u8地址 */
    private static String url = "http://playertest.longtailvideo.com/adaptive/bipbop/gear4/prog_index.m3u8";
    /** 正式文件存储地址(合并之后的文件) */
    private static String tofile = "E:\\m3u8\\Movie.ts";
    /** 临时文件存储地址(M3U8视频段) */
    private static String tofileTemp = "E:\\m3u8\\temp";
     
    private static ExecutorService executor = Executors.newFixedThreadPool(10);
 
    public static void main(String[] args) throws IOException, InterruptedException {
        //解析M3U8地址为对象
        M3U8 m3u8 = parseIndex(url);
 
        //根据M3U8对象获取时长
        float duration = getDuration(m3u8);
        System.out.println("时长: " + ((int) duration / 60) + "分" + (int) duration % 60 + "秒");
         
        //根据M3U8对象下载视频段
        download(m3u8, tofileTemp);
 
        //关闭线程池
        executor.shutdown();
        System.out.println("等待下载中...");
        while (!executor.isTerminated()) {
            Thread.sleep(100);
        }
 
        //合并文件
        merge(m3u8, tofile, tofileTemp);
         
        System.out.println("下载完成,合并的文件在: " + tofile);
    }
     
    /**
     * 根据M3U8对象获取时长
     * @param m3u8
     * @return
     */
    private static float getDuration(M3U8 m3u8){
        float duration = 0;
        for (M3U8Ts ts : m3u8.getTsList()) {
            duration += ts.getSeconds();
        }
        return duration;
    }
 
    /**
     * 合并文件
     * @param m3u8
     * @param tofile
     * @throws IOException
     */
    public static void merge(M3U8 m3u8, String tofile, String tofileTemp) throws IOException {
        File file = new File(tofile);
        FileOutputStream fos = new FileOutputStream(file);
         
        File fileTempDir = new File(tofileTemp);
        for (File fileTemp : fileTempDir.listFiles()) {
            IOUtils.copyLarge(new FileInputStream(fileTemp), fos);
        }
         
        fos.close();
    }
     
    /**
     * 根据M3U8对象下载视频段
     * @param m3u8
     * @param tofile
     * @throws IOException
     */
    public static void download(final M3U8 m3u8, final String tofileTemp) throws IOException {
        final File dir = new File(tofileTemp);
        if (!dir.exists()) {
            dir.mkdirs();
        }
 
        for (final M3U8Ts ts : m3u8.getTsList()) {
            executor.execute(new Runnable() {
                @Override
                public void run() {
                    try {
                        FileOutputStream writer = new FileOutputStream(new File(dir, ts.getFile()));
                        IOUtils.copyLarge(new URL(m3u8.getBasepath() + ts.getFile()).openStream(), writer);
                        writer.close();
                        System.out.println("视频段: " + ts + "下载完成");
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            });
        }
    }
 
    /**
     * 解析M3U8地址为对象
     * @param url M3U8地址
     */
    static M3U8 parseIndex(String url) throws IOException {
 
        BufferedReader reader = new BufferedReader(new InputStreamReader(new URL(url).openStream()));
 
        String basepath = url.substring(0, url.lastIndexOf("/") + 1);
 
        M3U8 ret = new M3U8();
        ret.setBasepath(basepath);
 
        String line;
        float seconds = 0;
        while ((line = reader.readLine()) != null) {
            if (line.startsWith("#")) {
                if (line.startsWith("#EXTINF:")) {
                    line = line.substring(8);
                    if (line.endsWith(",")) {
                        line = line.substring(0, line.length() - 1);
                    }
                    if (line.contains(",")) {
                        line = line.substring(0, line.indexOf(","));
                    }
                    seconds = Float.parseFloat(line);
                }
                continue;
            }
            if (line.endsWith("m3u8")) {
                return parseIndex(basepath + line);
            }
            ret.addTs(new M3U8Ts(line, seconds));
            seconds = 0;
        }
        reader.close();
 
        return ret;
    }
 
    static class M3U8 {
        private String basepath;
        private List<M3U8Ts> tsList = new ArrayList<M3U8Ts>();
 
        public String getBasepath() {
            return basepath;
        }
 
        public void setBasepath(String basepath) {
            this.basepath = basepath;
        }
 
        public List<M3U8Ts> getTsList() {
            return tsList;
        }
 
        public void setTsList(List<M3U8Ts> tsList) {
            this.tsList = tsList;
        }
 
        public void addTs(M3U8Ts ts) {
            this.tsList.add(ts);
        }
 
        @Override
        public String toString() {
            StringBuilder sb = new StringBuilder();
            sb.append("basepath: " + basepath);
            for (M3U8Ts ts : tsList) {
                sb.append("\nts: " + ts);
            }
 
            return sb.toString();
        }
 
    }
 
    static class M3U8Ts {
        private String file;
        private float seconds;
 
        public M3U8Ts(String file, float seconds) {
            this.file = file;
            this.seconds = seconds;
        }
 
        public String getFile() {
            return file;
        }
 
        public void setFile(String file) {
            this.file = file;
        }
 
        public float getSeconds() {
            return seconds;
        }
 
        public void setSeconds(float seconds) {
            this.seconds = seconds;
        }
 
        @Override
        public String toString() {
            return file + " (" + seconds + "sec)";
        }
    }
}
上一篇:m3u8


下一篇:解决EasyDSS、EasyNVR流媒体RTMP、HLS(m3u8)、HTTP-FLV播放提示H5播放错误的问题