网站联系我们页面服务器站点的网站地图怎么做
- 作者: 五速梦信息网
- 时间: 2026年03月21日 07:33
当前位置: 首页 > news >正文
网站联系我们页面,服务器站点的网站地图怎么做,牡丹江,成都qq推广学习链接
ffmpeg-demo 当前对应的 gitee代码
Spring boot视频播放(解决MP4大文件无法播放)#xff0c;整合ffmpeg,用m3u8切片播放。
springboot 通过javaCV 实现mp4转m3u8 上传oss
如何保护会员或付费视频#xff1f;优酷是怎么做的#xff1f; - HLS 流媒体加密
ffmpe…学习链接
ffmpeg-demo 当前对应的 gitee代码
Spring boot视频播放(解决MP4大文件无法播放)整合ffmpeg,用m3u8切片播放。
springboot 通过javaCV 实现mp4转m3u8 上传oss
如何保护会员或付费视频优酷是怎么做的 - HLS 流媒体加密
ffmpeg视频转切片m3u8并加密videojs播放hls.js播放dplayer播放弹幕效果
video标签学习 xgplayer视频播放器分段播放mp4
SpringBootFFmpeg实现上传视频到本地使用M3U8切片转码后下方使用hls.js播放支持mp4aviSpringBoot FFmpeg实现一个简单的M3U8切片转码系统 文章目录 学习链接简介效果图代码pom.xmlapplication.ymlWebConfigTestControllerFFmpegProcessorApp nginx配置player.html测试 简介
将上传的视频文件使用javacv拆分成m3u8文件和ts文件m3u8文件和ts文件通过nginx访问而key文件则通过web服务来获取。使用dplayer播放视频。
也可以使用ffmpeg命令来做可以参考上面链接。
当前能把mp4这样处理但是不能处理avi处理avi会报错处理avi的可以参考springboot-ffmpeg-m3u8-convertor - gitee代码或者这个springboot-ffmpeg-demo - gitee代码
效果图
m3u8文件和ts文件通过nginx访问而key文件则通过web服务来获取
拿不到key文件是无法播放的
代码
pom.xml
?xml version1.0 encodingUTF-8?
project xmlnshttp://maven.apache.org/POM/4.0.0xmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexsi:schemaLocationhttp://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsdparentgroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-parent/artifactIdversion2.3.4.RELEASE/versionrelativePath/ !– lookup parent from repository –/parentmodelVersion4.0.0/modelVersiongroupIdorg.example/groupIdartifactIdffmpeg-demo/artifactIdversion1.0-SNAPSHOT/versionpropertiesjava.version1.8/java.versionjavacv.version1.5.4/javacv.versionffmpeg.version4.3.1-1.5.4/ffmpeg.version/propertiesdependencies!–web 模块 –dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-web/artifactIdexclusions!–排除tomcat依赖 –exclusionartifactIdspring-boot-starter-tomcat/artifactIdgroupIdorg.springframework.boot/groupId/exclusion/exclusions/dependency!–undertow容器 –dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-undertow/artifactId/dependencydependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-test/artifactIdscopetest/scope/dependency!– javacv 和 ffmpeg的依赖包 –dependencygroupIdorg.bytedeco/groupIdartifactIdjavacv/artifactIdversion\({javacv.version}/versionexclusionsexclusiongroupIdorg.bytedeco/groupIdartifactId*/artifactId/exclusion/exclusions/dependencydependencygroupIdorg.bytedeco/groupIdartifactIdffmpeg-platform/artifactIdversion\){ffmpeg.version}/version/dependencydependencygroupIdcn.hutool/groupIdartifactIdhutool-all/artifactIdversion5.6.5/version/dependency/dependenciesbuildpluginsplugingroupIdorg.springframework.boot/groupIdartifactIdspring-boot-maven-plugin/artifactId/plugin/plugins/build/projectapplication.yml
server:port: 8080
spring:servlet:multipart:max-file-size: 500MBmax-request-size: 500MB
WebConfig
Configuration
public class WebConfig implements WebMvcConfigurer {Overridepublic void addResourceHandlers(ResourceHandlerRegistry registry) {registry.addResourceHandler(/test/).addResourceLocations(file: System.getProperty(user.dir) /test/);registry.addResourceHandler(/tmp/).addResourceLocations(file: System.getProperty(user.dir) /tmp/);}Overridepublic void addCorsMappings(CorsRegistry registry) {registry.addMapping(/).maxAge(3600).allowCredentials(true).allowedOrigins().allowedMethods().allowedHeaders().exposedHeaders(token,Authorization);}
}TestController
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.io.file.FileReader;
import cn.hutool.core.io.file.FileWriter;
import com.zzhua.processor.FFmpegProcessor;
import org.springframework.web.bind.annotation.;
import org.springframework.web.multipart.MultipartFile;import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.FileInputStream;
import java.io.IOException;RestController
public class TestController {/* 目录路径,这个路径需要包含test.info文件test.key文件和test.mp4文件/private static final String PATH D:\Projects\practice\ffmpeg-demo\test\;RequestMapping(uploadToM3u8)public void uploadToM3u8() throws Exception {FileInputStream inputStream new FileInputStream(PATH test.mp4);/ 这里原来的逻辑是1、m3u8Url是将生成的m3u8文件流写入的位置可以填写接收该请求的接口路径2、infoUrl是获取keyinfo文件的路径可以是接口路径3、上面2个都可以是本地路径/// String m3u8Url http://localhost:8080/upload/test.m3u8;// String infoUrl http://localhost:8080/preview/test.keyinfo;String m3u8Url D:\Projects\practice\ffmpeg-demo\test\test.m3u8;String infoUrl D:\Projects\practice\ffmpeg-demo\test\test.keyinfo;String segmentPattern http://localhost:8080/upload/test-%d.ts;FFmpegProcessor.convertMediaToM3u8ByHttp(inputStream, m3u8Url, infoUrl, segmentPattern);}RequestMapping(convertToM3u8)public void convertToM3u8(MultipartFile mfile) {FFmpegProcessor.convertMediaToM3u8(mfile);}PostMapping(upload/{fileName})public void upload(HttpServletRequest request, PathVariable(fileName) String fileName) throws IOException {ServletInputStream inputStream request.getInputStream();FileWriter writer new FileWriter(PATH fileName);writer.writeFromStream(inputStream);IoUtil.close(inputStream);}/** 预览加密文件/PostMapping(preview/{fileName})public void preview(PathVariable(fileName) String fileName, HttpServletResponse response) throws IOException {FileReader fileReader new FileReader(PATH fileName);fileReader.writeToStream(response.getOutputStream());}/** 预览加密文件/GetMapping(download/{fileName})public void download(PathVariable(fileName) String fileName, HttpServletResponse response) throws IOException {FileReader fileReader new FileReader(PATH fileName);fileReader.writeToStream(response.getOutputStream());}}FFmpegProcessor
import org.bytedeco.ffmpeg.avcodec.AVPacket;
import org.bytedeco.ffmpeg.global.avcodec;
import org.bytedeco.ffmpeg.global.avutil;
import org.bytedeco.javacv.;
import org.springframework.web.multipart.MultipartFile;import java.io.;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;public class FFmpegProcessor {/** 这个方法的url地址都必须是一样的类型 同为post/public static void convertMediaToM3u8ByHttp(InputStream inputStream, String m3u8Url, String infoUrl, String segmentPattern) throws IOException {avutil.av_log_set_level(avutil.AV_LOG_INFO);FFmpegLogCallback.set();FFmpegFrameGrabber grabber new FFmpegFrameGrabber(inputStream);grabber.start();FFmpegFrameRecorder recorder new FFmpegFrameRecorder(m3u8Url, grabber.getImageWidth(), grabber.getImageHeight(), grabber.getAudioChannels());recorder.setFormat(hls);// 拆分时间片段长度recorder.setOption(hls_time, 60);recorder.setOption(hls_list_size, 0);recorder.setOption(hls_flags, delete_segments);recorder.setOption(hls_delete_threshold, 1);recorder.setOption(hls_segment_type, mpegts);/ 这里指定生成的ts文件保存位置可以写接口路径, 该接口用于接收ts文件流*/// recorder.setOption(hls_segment_filename, http://localhost:8080/upload/test-%d.ts);recorder.setOption(hls_segment_filename, segmentPattern);recorder.setOption(hls_key_info_file, infoUrl);// http属性recorder.setOption(method, POST);recorder.setFrameRate(25);recorder.setGopSize(2 * 25);recorder.setVideoQuality(1.0);recorder.setVideoBitrate(10 * 1024);recorder.setVideoCodec(avcodec.AV_CODEC_ID_H264);recorder.setAudioCodec(avcodec.AV_CODEC_ID_AAC);/// 只保存图像而不保存声音recorder.start();Frame frame;while ((frame grabber.grabImage()) ! null) {try {recorder.record(frame);} catch (FrameRecorder.Exception e) {e.printStackTrace();}}recorder.setTimestamp(grabber.getTimestamp());recorder.close();grabber.close();//* 图像 声音 /recorder.start(grabber.getFormatContext());AVPacket packet;while ((packet grabber.grabPacket()) ! null) {try {recorder.recordPacket(packet);} catch (FrameRecorder.Exception e) {e.printStackTrace();}}recorder.setTimestamp(grabber.getTimestamp());recorder.stop();recorder.release();grabber.stop();grabber.release();}private static final String BASE_PATH System.getProperty(user.dir) \tmp\;public static void convertMediaToM3u8(MultipartFile mfile) {String origFileName mfile.getOriginalFilename();String fileName origFileName.substring(0, origFileName.lastIndexOf(.));String dirName fileName;String fileDir BASE_PATH fileName;File dirFile new File(fileDir);if (!dirFile.exists()) {dirFile.mkdirs();}try {File rawFile new File(dirFile, origFileName);// 保存文件mfile.transferTo(rawFile);// 生成密钥文件String commonFileName fileDir \ fileName;generateKeyFile(commonFileName .key);// 生成keyInfo文件generateKeyInfoFile(dirName, commonFileName .key, commonFileName .keyinfo);convertMediaToM3u8ByHttp(new FileInputStream(rawFile),commonFileName .m3u8,commonFileName .keyinfo,commonFileName -%d.ts);} catch (Exception e) {e.printStackTrace(System.err);}}/** 生成keyInfo文件** param keyFilePath 密钥文件路径* param keyInfoFilePath keyInfo文件路径/private static void generateKeyInfoFile(String dirName, String keyFilePath, String keyInfoFilePath) {try {// 生成IVProcessBuilder ivProcessBuilder new ProcessBuilder(openssl, rand, -hex, 16);Process ivProcess ivProcessBuilder.start();BufferedReader ivReader new BufferedReader(new InputStreamReader(ivProcess.getInputStream()));String iv ivReader.readLine();// 写入keyInfo文件String keyInfoContent http://127.0.0.1:8080/tmp/ dirName / new File(keyFilePath).getName() \n keyFilePath \n iv;Files.write(Paths.get(keyInfoFilePath), keyInfoContent.getBytes());System.out.println(keyInfo文件已生成: keyInfoFilePath);} catch (IOException e) {e.printStackTrace();}}/** 生成密钥文件** param keyFilePath 密钥文件路径*/private static void generateKeyFile(String keyFilePath) {try {ProcessBuilder processBuilder new ProcessBuilder(openssl, rand, 16);processBuilder.redirectOutput(new File(keyFilePath));Process process processBuilder.start();process.waitFor();System.out.println(密钥文件已生成: keyFilePath);} catch (IOException | InterruptedException e) {e.printStackTrace();}}
}App
SpringBootApplication
public class App {public static void main(String[] args) {SpringApplication.run(App.class, args);}}
nginx配置 #user nobody;
worker_processes 1;#error_log logs/error.log;
#error_log logs/error.log notice;
#error_log logs/error.log info;#pid logs/nginx.pid;events {worker_connections 1024;
}http {include mime.types;default_type application/octet-stream;server {listen 80;server_name localhost;add_header Access-Control-Allow-Origin \(http_origin always;add_header Access-Control-Allow-Methods GET, POST, PUT, DELETE, OPTIONS;add_header Access-Control-Allow-Headers Content-Type, Authorization, X-Requested-With, token;add_header Access-Control-Allow-Credentials true;location / {if (\)request_method OPTIONS) {return 204;}root D:/Projects/practice/ffmpeg-demo/tmp;}}}
player.html
!DOCTYPE html
html langenheadmeta charsetUTF-8meta nameviewport contentwidthdevice-width, initial-scale1.0titleDocument/titlestylebody {margin: 0;}.dplayer-container {width: 800px;height: 500px;display: flex;align-items: center;justify-content: center;}#dplayer {width: 100%;height: 100%;object-fit: cover;}/stylescript srchttps://cdn.jsdelivr.net/npm/hls.jslatest/scriptscript srchttps://cdn.jsdelivr.net/npm/dplayer1.27.1/dist/DPlayer.min.js/script
/headbodydiv classdplayer-containerdiv iddplayer/div/divhr /script// 另一种方式使用 customTypeconst dp new DPlayer({container: document.getElementById(dplayer),autoplay: false, // 自动播放video: {url: http://127.0.0.1/zzhua/zzhua.m3u8,type: customHls,customType: {customHls: function (video, player) {const hls new Hls();hls.loadSource(video.src);hls.attachMedia(video);},},},});Window.dp dp;/script
/body/html
测试
上传1个301M的视频耗时15s 共188个文件其中184个ts文件 播放效果
相关文章
-
网站联系方式修改衡阳市做淘宝网站建设
网站联系方式修改衡阳市做淘宝网站建设
- 技术栈
- 2026年03月21日
-
网站联盟系统天津河东网站建设公司
网站联盟系统天津河东网站建设公司
- 技术栈
- 2026年03月21日
-
网站联盟接口怎么做个人主页网址
网站联盟接口怎么做个人主页网址
- 技术栈
- 2026年03月21日
-
网站链接的基本形式wordpress仿seowhy基础指南模板
网站链接的基本形式wordpress仿seowhy基础指南模板
- 技术栈
- 2026年03月21日
-
网站链接的基本形式那么多网站都是谁做的
网站链接的基本形式那么多网站都是谁做的
- 技术栈
- 2026年03月21日
-
网站链接推广工具做网站建设多少钱
网站链接推广工具做网站建设多少钱
- 技术栈
- 2026年03月21日
