当前位置: 首页 > news >正文

网站建设管理工作深圳媒体网络推广有哪些

网站建设管理工作,深圳媒体网络推广有哪些,网站在哪里设置关键字,一键logo设计官网上图就是大致的流程一、标题图片上传课程的标题图片Ajax发送请求到后端后端接收到图片使用IO流去保存图片,返回图片的信息对象JS回调函数接收对象通过$("元素id").val(值),方式给页面form表达img标签src属性值,达到上传图片并回显二…

上图就是大致的流程


一、标题图片

  1. 上传课程的标题图片

  1. Ajax发送请求到后端

  1. 后端接收到图片使用IO流去保存图片,返回图片的信息对象

  1. JS回调函数接收对象通过$("元素id").val(值),方式给页面form表达img标签src属性值,达到上传图片并回显

二、大文件上传(流媒体、音频、.zip文件等)

  1. 页面div点击事件,选中一个视频文件

  1. JS判断文件大小,判断文件类型是否合法

3.JS循环切片,计算总片数,计算每一片的起始位置,循环上传

4.发送Ajax转给后端切片

5.后端接收并创建临时目录存放

    /*** 分片上传,前端调用此方法* @param request* @param guid* @param chunk* @param file* @return*/@PostMapping("/uploadSlice")@ResponseBodypublic ResponseResult<?> uploadSlice2(HttpServletRequest request, @RequestParam("guid") String guid,@RequestParam("chunk") Integer chunk,@RequestParam("file") MultipartFile file) {if (this.uploadSlice(request, guid, chunk, file)){return ResponseResultUtils.genResult("上传成功","");}else{return ResponseResultUtils.genErrorResult("上传失败");}}/*** 分片上传的具体方法* @param request* @param guid* @param chunk* @param file* @return*/private boolean uploadSlice(HttpServletRequest request, String guid, Integer chunk, MultipartFile file) {try {boolean isMultipart = ServletFileUpload.isMultipartContent(request);logger.info("isMultipart = {}",isMultipart);if (isMultipart) {if (chunk == null){chunk = 0;}// 临时目录用来存放所有分片文件String tempFileDir =  rootFilePath + bigPath + guid;File parentFileDir = new File(tempFileDir);if (!parentFileDir.exists()) {parentFileDir.mkdirs();}logger.info("接到上传的分片文件,{},{},{}",guid,chunk,tempFileDir);// 分片处理时,前台会多次调用上传接口,每次都会上传文件的一部分到后台File tempPartFile = new File(parentFileDir, guid + "_" + chunk + ".part");FileUtils.copyInputStreamToFile(file.getInputStream(), tempPartFile);}} catch (Exception e) {return false;}return true;}

6.计数器变量值=总片数时,发送合并请求

7.后端合并

/*** 分片文件合并,前端调用此方法* @param guid* @param fileName* @return*/@RequestMapping("/uploadMerge")@ResponseBodypublic ResponseResult<?> uploadMerge2(@RequestParam("guid") String guid, @RequestParam("fileName") String fileName) {// 得到 destTempFile 就是最终的文件SpaceImage image = this.uploadMerge(guid, fileName);if(null != imageSpaceImage){return ResponseResultUtils.genResult(imageSpaceImage,"合并成功");}else{return ResponseResultUtils.genErrorResult("合并文件失败");}}private ImageSpaceImage uploadMerge(String guid, String fileName){SpaceImage image = mergeFile(guid, fileName);//此处需要注意,OSS需要再次切片上传,但minIO是不用得,它默认5M超过就会自动切片String path = "";//移除文件poolTaskExecutor.execute(() -> {com.eyang.ecpp.utils.FileUtils.deleteFile(rootFilePath+bigPath);});return imageSpaceImage;}private ImageSpaceImage mergeFile(String guid, String fileName) {logger.info("接到上传的分片文件合并请求,{},{}",guid,fileName);try {String sName = fileName.substring(fileName.lastIndexOf("."));//时间格式化格式Date currentTime = new Date();SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMddHHmmssSSS");//获取当前时间并作为时间戳String timeStamp = simpleDateFormat.format(currentTime);//拼接新的文件名String newName = timeStamp + sName;simpleDateFormat = new SimpleDateFormat("yyyyMM");String tempPath = rootFilePath + bigPath+guid;String margePath = rootFilePath + bigPath+simpleDateFormat.format(currentTime);File parentFileDir = new File(tempPath);if (parentFileDir.isDirectory()) {File destTempFile = new File(margePath, newName);if (!destTempFile.exists()) {//先得到文件的上级目录,并创建上级目录,在创建文件destTempFile.getParentFile().mkdir();destTempFile.createNewFile();}for (int i = 0; i < Objects.requireNonNull(parentFileDir.listFiles()).length; i++) {File partFile = new File(parentFileDir, guid + "_" + i + ".part");FileOutputStream destTempfos = new FileOutputStream(destTempFile, true);//遍历"所有分片文件"到"最终文件"中FileUtils.copyFile(partFile, destTempfos);destTempfos.close();}// 删除临时目录中的分片文件FileUtils.deleteDirectory(parentFileDir);String[] resultArr = FileStorageUtils.saveBigFile(Files.readAllBytes(Paths.get(destTempFile.getPath())), com.eyang.ecpp.utils.FileUtils.getExtension(destTempFile.getName()));ImageSpaceImage imageSpaceImage = new ImageSpaceImage();//第一个是组名 第二个是改后的文件名imageSpaceImage.setImgUrl(margePath+"/"+newName);//imageSpaceImage.setName(destTempFile.getName());imageSpaceImage.setName(fileName);return imageSpaceImage;//destTempFile.getAbsolutePath();}} catch (Exception e) {logger.error("切片文件合并,失败原因e:{}", e.getMessage());}return null;}

8.合并成功后进行转码

转码需要下载一个ffmpeg,下载完解压打开bin目录,打开电脑的环境变量往path中添加上bin的目录即可。

还需要引入依赖

 <!--  视频编码 -->
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.6</version>
</dependency>

9.转码发送请求

10.后端转码

/*** 视频编码** @param absolutePath 绝对路径* @return {@link ResponseResult}<{@link ?}>*/@RequiresPermissions("cms:article:edit")@RequestMapping(value = "video/coding")@ResponseBodypublic ResponseResult<?> videoCoding(@RequestParam String absolutePath) {TranscodeConfig transcodeConfig = new TranscodeConfig();//设置视频封面transcodeConfig.setPoster("1");transcodeConfig.setTsSeconds("60");ResponseResult<?> transResult = TranscodeFileUtils.transCodeFile(absolutePath, transcodeConfig);String retUrl = "";if (null != transResult) {Map<String, Object> data = (Map<String, Object>) transResult.getData();if (null != data) {Map<String, Object> videoInfo = (Map<String, Object>) data.get("data");if (null != videoInfo) {retUrl = (String) videoInfo.get("m3u8");}}}return ResponseResultUtils.genResult(retUrl,"转码成功");}

视频转码配置实体类

package com.utils;public class TranscodeConfig {private String poster; // 截取封面的时间private String tsSeconds; // ts分片大小,单位是秒private String cutStart; // 视频裁剪,开始时间private String cutEnd; // 视频裁剪,结束时间public String getPoster() {return poster;}public void setPoster(String poster) {this.poster = poster;}public String getTsSeconds() {return tsSeconds;}public void setTsSeconds(String tsSeconds) {this.tsSeconds = tsSeconds;}public String getCutStart() {return cutStart;}public void setCutStart(String cutStart) {this.cutStart = cutStart;}public String getCutEnd() {return cutEnd;}public void setCutEnd(String cutEnd) {this.cutEnd = cutEnd;}public TranscodeConfig() {}public TranscodeConfig(String poster, String tsSeconds, String cutStart, String cutEnd) {this.poster = poster;this.tsSeconds = tsSeconds;this.cutStart = cutStart;this.cutEnd = cutEnd;}
}

转码工具类

public class TranscodeFileUtils {/*** 视频根路径*/private static String videoFolder= Global.getConfig("video.folder");private static final Logger LOGGER = LoggerFactory.getLogger(TranscodeFileUtils.class);public static ResponseResult<Map<String, Object>> transCodeFile(String filePath, TranscodeConfig transcodeConfig){try {// 按照日期生成子目录String today = DateTimeFormatter.ofPattern("yyyyMMdd").format(LocalDate.now());String s = Identities.uuid2();Path targetFolder = Paths.get(videoFolder, today, s);// 执行转码操作LOGGER.info("开始转码");FFmpegUtils.transcodeToM3u8(filePath, targetFolder.toString(), transcodeConfig);// 封装结果Map<String, Object> videoInfo = new HashMap<>();videoInfo.put("m3u8", String.join("\\", targetFolder.toString(), "index.m3u8"));videoInfo.put("poster", String.join("\\", targetFolder.toString(), "poster.jpg"));Map<String, Object> result = new HashMap<>();result.put("success", true);result.put("data", videoInfo);return ResponseResultUtils.genResult(result,"转码成功!");} catch (Exception e) {e.printStackTrace();}return null;}public static void main(String[] args){System.out.println(TranscodeFileUtils.transCodeFile("E:\\录屏\\shipin\\test.mp4", new TranscodeConfig("00:00:00.001","15","","")));}}

转码工具类

public class FFmpegUtils {private static final Logger LOGGER = LoggerFactory.getLogger(FFmpegUtils.class);// 跨平台换行符private static final String LINE_SEPARATOR = System.getProperty("line.separator");/*** 生成随机16个字节的AESKEY* @return*/private static byte[] genAesKey ()  {try {KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");keyGenerator.init(128);return keyGenerator.generateKey().getEncoded();} catch (NoSuchAlgorithmException e) {return null;}}/*** 在指定的目录下生成key_info, key文件,返回key_info文件* @param folder* @throws IOException*/private static Path genKeyInfo(String folder) throws IOException {// AES 密钥byte[] aesKey = genAesKey();// AES 向量String iv = Hex.encodeHexString(genAesKey());// key 文件写入Path keyFile = Paths.get(folder, "key");Files.write(keyFile, aesKey, StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING);// key_info 文件写入StringBuilder stringBuilder = new StringBuilder();stringBuilder.append("key").append(LINE_SEPARATOR);                    // m3u8加载key文件网络路径stringBuilder.append(keyFile.toString()).append(LINE_SEPARATOR);    // FFmeg加载key_info文件路径stringBuilder.append(iv);                                            // ASE 向量Path keyInfo = Paths.get(folder, "key_info");Files.write(keyInfo, stringBuilder.toString().getBytes(), StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING);return keyInfo;}/*** 指定的目录下生成 master index.m3u8 文件* @param file            master m3u8文件地址* @param indexPath            访问子index.m3u8的路径* @param bandWidth            流码率* @throws IOException*/private static void genIndex(String file, String indexPath, String bandWidth) throws IOException {StringBuilder stringBuilder = new StringBuilder();stringBuilder.append("#EXTM3U").append(LINE_SEPARATOR);stringBuilder.append("#EXT-X-STREAM-INF:BANDWIDTH=" + bandWidth).append(LINE_SEPARATOR);  // 码率stringBuilder.append(indexPath);Files.write(Paths.get(file), stringBuilder.toString().getBytes(StandardCharsets.UTF_8), StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING);}/*** 转码视频为m3u8* @param source                源视频* @param destFolder            目标文件夹* @param config                配置信息* @throws IOException* @throws InterruptedException*/public static void transcodeToM3u8(String source, String destFolder, TranscodeConfig config) throws IOException, InterruptedException {// 判断源视频是否存在if (!Files.exists(Paths.get(source))) {throw new IllegalArgumentException("文件不存在:" + source);}// 创建工作目录Path workDir = Paths.get(destFolder, "ts");Files.createDirectories(workDir);// 在工作目录生成KeyInfo文件Path keyInfo = genKeyInfo(workDir.toString());// 构建命令List<String> commands = new ArrayList<>();commands.add("ffmpeg");commands.add("-i");commands.add(source);                    // 源文件commands.add("-c:v");commands.add("libx264");                // 视频编码为H264commands.add("-c:a");commands.add("copy");                    // 音频直接copycommands.add("-hls_key_info_file");commands.add(keyInfo.toString());        // 指定密钥文件路径commands.add("-hls_time");commands.add(config.getTsSeconds());    // ts切片大小commands.add("-hls_playlist_type");commands.add("vod");                    // 点播模式commands.add("-hls_segment_filename");commands.add("%06d.ts");                // ts切片文件名称if (StringUtils.hasText(config.getCutStart())) {commands.add("-ss");commands.add(config.getCutStart());    // 开始时间}if (StringUtils.hasText(config.getCutEnd())) {commands.add("-to");commands.add(config.getCutEnd());        // 结束时间}commands.add("index.m3u8");                                                        // 生成m3u8文件// 构建进程Process process = new ProcessBuilder().command(commands).directory(workDir.toFile()).start();// 读取进程标准输出new Thread(() -> {try (BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(process.getInputStream()))) {String line = null;while ((line = bufferedReader.readLine()) != null) {LOGGER.info(line);}} catch (IOException e) {}}).start();// 读取进程异常输出new Thread(() -> {try (BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(process.getErrorStream()))) {String line = null;while ((line = bufferedReader.readLine()) != null) {LOGGER.info(line);}} catch (IOException e) {}}).start();// 阻塞直到任务结束if (process.waitFor() != 0) {throw new RuntimeException("视频切片异常");}// 切出封面if (!screenShots(source, String.join(File.separator, destFolder, "poster.jpg"), config.getPoster())) {throw new RuntimeException("封面截取异常");}// 获取视频信息MediaInfo mediaInfo = getMediaInfo(source);if (mediaInfo == null) {throw new RuntimeException("获取媒体信息异常");}// 生成index.m3u8文件genIndex(String.join(File.separator, destFolder, "index.m3u8"), "ts/index.m3u8", mediaInfo.getFormat().getBitRate());// 删除keyInfo文件Files.delete(keyInfo);}/*** 获取视频文件的媒体信息* @param source* @return* @throws IOException* @throws InterruptedException*/public static MediaInfo getMediaInfo(String source) throws IOException, InterruptedException {List<String> commands = new ArrayList<>();commands.add("ffprobe");commands.add("-i");commands.add(source);commands.add("-show_format");commands.add("-show_streams");commands.add("-print_format");commands.add("json");Process process = new ProcessBuilder(commands).start();MediaInfo mediaInfo = null;try (BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(process.getInputStream()))) {mediaInfo = new Gson().fromJson(bufferedReader, MediaInfo.class);} catch (IOException e) {e.printStackTrace();}if (process.waitFor() != 0) {return null;}return mediaInfo;}/*** 截取视频的指定时间帧,生成图片文件* @param source        源文件* @param file            图片文件* @param time            截图时间 HH:mm:ss.[SSS]* @throws IOException* @throws InterruptedException*/public static boolean screenShots(String source, String file, String time) throws IOException, InterruptedException {List<String> commands = new ArrayList<>();commands.add("ffmpeg");commands.add("-i");commands.add(source);commands.add("-ss");commands.add(time);commands.add("-y");commands.add("-q:v");commands.add("1");commands.add("-frames:v");commands.add("1");commands.add("-f");commands.add("image2");commands.add(file);Process process = new ProcessBuilder(commands).start();// 读取进程标准输出new Thread(() -> {try (BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(process.getInputStream()))) {String line = null;while ((line = bufferedReader.readLine()) != null) {LOGGER.info(line);}} catch (IOException e) {}}).start();// 读取进程异常输出new Thread(() -> {try (BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(process.getErrorStream()))) {String line = null;while ((line = bufferedReader.readLine()) != null) {LOGGER.error(line);}} catch (IOException e) {}}).start();return process.waitFor() == 0;}}

11.转码成功返回m3u8文件的路径,放到页面input隐藏标签中

编码成功后执行回调函数,m3u8文件赋给_data变量如下图

使用$(#页面元素id).val(值),下图是把m3u8赋值给页面的input

12.最后页面form提交,保存视频转码后m3u8的路径。

http://www.15wanjia.com/news/28521.html

相关文章:

  • 休闲食品网站建设策划书搜索引擎优化排名seo
  • 嘉兴网站建设技术托管北京网站seo招聘
  • 网站做非经营性广告需备案佛山seo网站排名
  • 上海内贸网站建设seo优化顾问服务阿亮
  • 网站服务器地址怎么查如何进行关键词分析
  • 设计官网推荐上海专业seo服务公司
  • 二级域名做网站注意找百度
  • 建设银行咸阳交费网站青岛seo排名收费
  • 烟台H5高端网站建设网络营销的策划方案
  • 网站开发的前后端是哪些百度推广创意范例
  • 天津专业网站建设公司南宁关键词优化公司
  • 网站做qq链接seo网络培训学校
  • excel可以做网站吗广东百度seo关键词排名
  • 荔湾网站建设公司沧州网站推广优化
  • 怎么在子域名建立一个不同的网站热搜榜排名前十
  • 站长统计 网站统计重庆网站建设维护
  • 微信官方网站培训机构网站
  • 做网站可以临摹吗seo营销培训咨询
  • 济南精品建站外包公司价格网店推广方案范文
  • seo 优化教程正规seo关键词排名哪家专业
  • 谷歌做公司网站需要多少钱灰色词网站seo
  • 网络科技公司网站制作免费的网站推广平台
  • 网站免费推广怎么做网站建设流程
  • 莆田企业自助建站西安seo关键词推广
  • 中企动力建站怎么样北京网站快速优化排名
  • 网络最好的运营商seo关键词排名优化系统
  • 企业建站系统信息免费发布友链
  • 上海专做特卖的网站2345网址大全下载到桌面
  • 淄博那里有做网站的上海最近三天的新闻
  • 国内大中型网站建设知名公司怎么投放广告