springmvc环境下 ffmpeg 解析视频,生成缩略图,视频转码m3u8并加密,同时设置是否保留原视频

前阵子研究了下视频转码,公司需要视频加密,虽然加密m3u8直播流的形式并不能完全阻止有心人下载视频(有心人利用第三方软件可以下载转码成mp4,或者直接录屏),但掌握技术符合公司需求就好,鉴于我只是普通后台开发人员,所以画了个最基本交互页面,如下图


解决思路:首先读取配置文件,然后根据大家的需求修改并保存,讲保存的结果注入到配置文件中,配置文件如下

ifStart=0
url=E:/scipmedresource
format=.rmvb,.flv,.mp4,.mov,.3gp,.mkv,.avi,wmv
time = 10
isDelete =0
jpgSize =420x320
returnPath =
ffmpegPath =E\:/ffmpeg/bin/ffmpeg.exe
当点击开始的时候改变ifstart的值,然后利用spring定时器,定时扫描转码加密 具体代码如下

   @Scheduled(cron = "0/20 * * * * ? ")
	public void toIndex() throws IOException, InterruptedException {
		Properties prop = new Properties();
		InputStream in = this.getClass().getClassLoader().getResourceAsStream("config.properties");

		prop.load(in); // /加载属性列表
		// 是否开始转码
		String ifStart = prop.getProperty("ifStart");
		// 文件夹路径
		String url = prop.getProperty("url");
		// 文件支持类型
		String format = prop.getProperty("format");
		// 切片时间
		String time = prop.getProperty("time");
		// 是否删除源文件
		final String isDelete = prop.getProperty("isDelete");
		// 缩略图大小
		String jpgSize = prop.getProperty("jpgSize");
		// 成功返回地址
		String returnPath = prop.getProperty("returnPath");
		// 软件路径
		String ffmpegPath = prop.getProperty("ffmpegPath");

		in.close();
		File file = new File(url);
		List<String> list = new ArrayList<String>();
		if (ifStart.equals("1")) {
			List<String> fileList = getAllVideo(url, file, list, format);
			for (String f : fileList) {

				// 创建文件夹
				String mkdir = f.substring(0, f.lastIndexOf("."));
				File realwatermarkDirFile = new File(mkdir);
				// Check
				if (!realwatermarkDirFile.exists() && !realwatermarkDirFile.isDirectory()) {
					realwatermarkDirFile.mkdir();
				}

				String scan = f.substring(0, f.lastIndexOf(".")) + ".scan";
				File scanFile = new File(scan);
				if (!scanFile.exists()) {
					scanFile.createNewFile();
				}

				// key和keyinfo文件
				writeKey(mkdir);
				writeKeyInfo(mkdir);
				// 获取缩略图
				List<String> commend = new ArrayList<String>();
				commend.add(ffmpegPath);
				commend.add("-i");
				commend.add(f);
				commend.add("-y");
				commend.add("-f");
				commend.add("image2");
				commend.add("-ss");
				commend.add("10");
				commend.add("-t");
				commend.add("0.001");
				commend.add("-s");
				commend.add(jpgSize);
				commend.add(mkdir + "/1.jpg");
				ProcessBuilder builder = new ProcessBuilder(commend);
				builder.command(commend);
				builder.start();
				// 加密转码
				List<String> commend1 = new ArrayList<String>();
				commend1.add(ffmpegPath);
				commend1.add("-i");
				commend1.add(f);
				commend1.add("-acodec");
				commend1.add("copy");
				commend1.add("-vcodec");
				commend1.add("copy");
				commend1.add("-c:v");
				commend1.add("libx264");
				commend1.add("-f");
				commend1.add("hls");
				commend1.add("-hls_time");
				commend1.add(time);
				commend1.add("-hls_list_size");
				commend1.add("0");
				commend1.add("-hls_key_info_file");
				commend1.add(mkdir + "/key_info");
				commend1.add(mkdir + "/index.m3u8");
				ProcessBuilder builder1 = new ProcessBuilder(commend1);
				builder1.command(commend1);

				try {
					final Process process = builder1.start();
					// 处理InputStream的线程
					new Thread() {
						@Override
						public void run() {
							InputStream input = process.getInputStream();
							InputStreamReader isr = new InputStreamReader(input);
							BufferedReader in = new BufferedReader(isr);
							String line = null;

							try {
								while ((line = in.readLine()) != null) {
									System.out.println("output: " + line);
								}
							} catch (IOException e) {
								e.printStackTrace();
							} finally {
								try {
									in.close();
									isr.close();
									input.close();
								} catch (IOException e) {
									e.printStackTrace();
								}
							}
						}
					}.start();

					new Thread() {
						@Override
						public void run() {
							InputStream input = process.getErrorStream();
							InputStreamReader isr = new InputStreamReader(input);
							BufferedReader err = new BufferedReader(isr);
							String line = null;

							try {
								while ((line = err.readLine()) != null) {
									System.out.println("err: " + line);
								}

							} catch (IOException e) {
								e.printStackTrace();
							} finally {
								try {
									err.close();
									isr.close();
									input.close();
								} catch (IOException e) {
									e.printStackTrace();
								}
							}
						}
					}.start();

					process.waitFor();
					if (isDelete.equals("1")) {

						String scan1 = f.substring(0, f.lastIndexOf(".")) + ".scan";
						File fileScan = new File(scan1);
						if (fileScan.exists()) {
							fileScan.delete();
						}

						boolean result = false;
						int i = 0;
						while (!result) {
							i++;
							File gcFile = new File(f);
							result = gcFile.delete();
							System.gc();
							if (result) {
								System.out.println("第" + i + "次为:" + result);
							}

						}

					}
					if (!returnPath.equals("")) {
						// 根据地址获取请求
						HttpGet request = new HttpGet(returnPath + "?name=" + f);// 这里发送get请求
						// 获取当前客户端对象
						HttpClient httpClient = new DefaultHttpClient();
						// 通过请求对象获取响应对象
						HttpResponse response = httpClient.execute(request);
					}

				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		}
	}

	private static List<String> getAllVideo(String url, File file, List<String> list, String format) {
		String[] filelist = file.list();
		String[] formats = format.split(",");
		for (int i = 0; i < filelist.length; i++) {
			File readfile = new File(url + "\\" + filelist[i]);
			if (!readfile.isDirectory()) {
				for (String f : formats) {
					if (readfile.getName().indexOf(f) > -1) {

						String scan = readfile.getAbsolutePath().substring(0, readfile.getAbsolutePath().lastIndexOf("."));
						scan += ".scan";
						File fileScan = new File(scan);
						if (!fileScan.exists()) {

							list.add(readfile.getAbsolutePath());
						}
						break;
					}
				}
			} else {
				getAllVideo(readfile.getPath(), readfile, list, format);
			}
		}
		return list;

	}

	/**
	 * 生成key
	 * 
	 * @author 李禚
	 * @date 2017-10-18上午11:28:44
	 */
	private static void writeKey(String mkdir) throws IOException {
		FileOutputStream fos = null;
		PrintWriter pw = null;

		File file = new File(mkdir + "\\" + "key.key");// 文件路径(包括文件名称)
		// 将文件读入输入流
		StringBuffer buffer = new StringBuffer();

		buffer.append(getStringRandom(16));
		// buffer.append("3aa1c008d8effdbc");
		try {
			fos = new FileOutputStream(file);
			pw = new PrintWriter(fos);
			pw.write(buffer.toString().toCharArray());
			pw.flush();
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if (pw != null) {
				pw.close();
			}
			if (fos != null) {
				fos.close();
			}
		}

	}

	/**
	 * 生成keyinfo
	 * 
	 * @author 李禚
	 * @date 2017-10-18上午11:28:22
	 */
	private static void writeKeyInfo(String mkdir) throws IOException {
		FileOutputStream fos = null;
		PrintWriter pw = null;

		File file = new File(mkdir + "\\" + "key_info");// 文件路径(包括文件名称)
		// 将文件读入输入流
		StringBuffer buffer = new StringBuffer();

		buffer.append("key.key\n");
		buffer.append(mkdir + "\\key.key");
		try {
			fos = new FileOutputStream(file);
			pw = new PrintWriter(fos);
			pw.write(buffer.toString().toCharArray());
			pw.flush();
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if (pw != null) {
				pw.close();
			}
			if (fos != null) {
				fos.close();
			}
		}

	}

	/**
	 * 生成16位字母和数字
	 * 
	 * @author 李禚
	 * @date 2017-10-18上午11:26:03
	 */
	private static String getStringRandom(int length) {

		String val = "";
		Random random = new Random();

		// 参数length,表示生成几位随机数
		for (int i = 0; i < length; i++) {

			String charOrNum = random.nextInt(2) % 2 == 0 ? "char" : "num";
			// 输出字母还是数字
			if ("char".equalsIgnoreCase(charOrNum)) {
				// 小写字母
				int temp = 97;
				val += (char) (random.nextInt(26) + temp);
			} else if ("num".equalsIgnoreCase(charOrNum)) {
				val += String.valueOf(random.nextInt(10));
			}
		}
		return val;
	}

具体参数含义可以查看ffmepg官方网站http://ffmpeg.org/

ok加密转码服务搞定,如有疑问或问题请多多指教

猜你喜欢

转载自blog.csdn.net/qq_20948277/article/details/79159007
今日推荐