Azure Media Service退役后,能否用Azure Function将AVI转MP4?
AVI转MP4编码解决方案(Azure Function替代Azure Media Service)
针对你遇到的JAVE2/FFmpeg依赖本地文件、无法直接处理Blob输入流的问题,结合输入文件最大100MB的限制,可通过临时文件中转的方式解决,以下是具体实现方案:
方案一:使用JAVE2实现编码
JAVE2确实依赖java.io.File作为输入输出载体,我们可以先将Blob中的AVI文件写入本地临时文件,编码完成后再将输出的MP4文件上传回Blob存储。
核心步骤
- 从Blob获取输入流,写入临时文件
- 用JAVE2对临时AVI文件进行编码,输出为临时MP4文件
- 将临时MP4文件转为输入流,上传至目标Blob容器
- 清理临时文件,避免占用资源
代码示例
import com.azure.storage.blob.BlobClient; import ws.schild.jave.Encoder; import ws.schild.jave.EncoderException; import ws.schild.jave.MultimediaObject; import ws.schild.jave.encode.AudioAttributes; import ws.schild.jave.encode.EncodingAttributes; import ws.schild.jave.encode.VideoAttributes; import java.io.*; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.StandardCopyOption; public class AviToMp4Converter { public void convertAviToMp4(BlobClient sourceBlobClient, BlobClient targetBlobClient) throws IOException, EncoderException { // 创建临时AVI文件 Path tempAviPath = Files.createTempFile("temp-", ".avi"); File tempAviFile = tempAviPath.toFile(); // 将Blob输入流写入临时文件 try (InputStream blobInputStream = sourceBlobClient.openInputStream()) { Files.copy(blobInputStream, tempAviPath, StandardCopyOption.REPLACE_EXISTING); } try { // 创建临时MP4输出文件 Path tempMp4Path = Files.createTempFile("output-", ".mp4"); File tempMp4File = tempMp4Path.toFile(); // 配置JAVE2编码参数 AudioAttributes audio = new AudioAttributes(); audio.setCodec("aac"); audio.setBitRate(128000); audio.setChannels(2); audio.setSamplingRate(44100); VideoAttributes video = new VideoAttributes(); video.setCodec("h264"); video.setBitRate(2000000); video.setFrameRate(25); EncodingAttributes attrs = new EncodingAttributes(); attrs.setOutputFormat("mp4"); attrs.setAudioAttributes(audio); attrs.setVideoAttributes(video); // 执行编码操作 Encoder encoder = new Encoder(); encoder.encode(new MultimediaObject(tempAviFile), tempMp4File, attrs); // 将MP4文件上传至Blob try (InputStream mp4InputStream = new FileInputStream(tempMp4File)) { targetBlobClient.upload(mp4InputStream, tempMp4File.length()); } finally { // 清理临时MP4文件 Files.deleteIfExists(tempMp4Path); } } finally { // 清理临时AVI文件 Files.deleteIfExists(tempAviPath); } } }
方案二:使用FFmpeg实现编码
如果JAVE2的封装无法满足需求,直接调用FFmpeg进程会更灵活,同样通过临时文件中转实现:
核心步骤
- 下载Blob中的AVI到临时文件
- 调用FFmpeg进程将AVI转码为MP4临时文件
- 上传MP4临时文件至Blob
- 清理临时文件
代码示例
import com.azure.storage.blob.BlobClient; import java.io.*; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.StandardCopyOption; public class FfmpegConverter { public void convertWithFfmpeg(BlobClient sourceBlobClient, BlobClient targetBlobClient) throws IOException, InterruptedException { // 创建临时AVI文件 Path tempAviPath = Files.createTempFile("temp-", ".avi"); File tempAviFile = tempAviPath.toFile(); // 将Blob内容写入临时文件 try (InputStream blobInputStream = sourceBlobClient.openInputStream()) { Files.copy(blobInputStream, tempAviPath, StandardCopyOption.REPLACE_EXISTING); } try { // 创建临时MP4输出文件 Path tempMp4Path = Files.createTempFile("output-", ".mp4"); File tempMp4File = tempMp4Path.toFile(); // 构建FFmpeg转码命令(需确保Azure Function环境已安装FFmpeg) String ffmpegCmd = String.format( "ffmpeg -i %s -c:v libx264 -c:a aac -b:a 128k %s", tempAviFile.getAbsolutePath(), tempMp4File.getAbsolutePath() ); // 执行FFmpeg进程 Process process = new ProcessBuilder("bash", "-c", ffmpegCmd).start(); int exitCode = process.waitFor(); if (exitCode != 0) { throw new RuntimeException("FFmpeg转码失败,退出码:" + exitCode); } // 上传MP4文件至Blob try (InputStream mp4InputStream = new FileInputStream(tempMp4File)) { targetBlobClient.upload(mp4InputStream, tempMp4File.length()); } finally { Files.deleteIfExists(tempMp4Path); } } finally { Files.deleteIfExists(tempAviPath); } } }
注意事项
- Azure Function环境需预先安装FFmpeg:Linux环境可通过自定义Docker镜像或启动脚本安装;Windows环境需将FFmpeg二进制文件打包进函数部署包。
- 临时文件存储:Azure Function提供的临时目录(
/tmp或%TEMP%)足够容纳100MB的文件,无需担心空间问题。
内容的提问来源于stack exchange,提问作者Sandy
相关产品推荐
相关产品推荐

