GO语言实现视频分割
2023-12-18 18:36:05
视频分割
每隔10秒分割一次,去掉分割视频的最后0.5秒,合并后删除分割视频
package main
import (
"fmt"
"io/ioutil"
"log"
"os"
"os/exec"
"path/filepath"
"strconv"
"strings"
)
func main() {
videoPath := "C:\\move\\video.mp4" // 视频文件路径
outputDir := "C:\\move\\output\\" // 分割后的视频保存目录
segmentDuration := 10 // 每个片段的时长(秒)
// 创建保存目录
err := os.MkdirAll(outputDir, 0755)
if err != nil {
log.Fatal(err)
}
// 使用FFprobe获取视频时长
duration, err := getVideoDuration(videoPath)
if err != nil {
log.Fatal(err)
}
fmt.Println("视频时长:", duration)
// 分割视频
segments := []string{}
for i := 0; i < duration; i += segmentDuration {
outputPath := filepath.Join(outputDir, fmt.Sprintf("segment_%d.mp4", i))
err := splitVideoSegment(videoPath, outputPath, i, segmentDuration)
if err != nil {
log.Fatal(err)
}
fmt.Printf("已分割片段: %s\n", outputPath)
segments = append(segments, outputPath)
}
// 合并视频
outputPath := filepath.Join(outputDir, "merged.mp4")
err = mergeVideos(segments, outputPath)
if err != nil {
log.Fatal(err)
}
fmt.Printf("已合并视频: %s\n", outputPath)
// 删除分割视频
err = deleteSegmentFiles(segments)
if err != nil {
log.Fatal(err)
}
}
// 使用FFprobe获取视频时长
func getVideoDuration(videoPath string) (int, error) {
cmd := exec.Command("ffprobe", "-v", "error", "-show_entries", "format=duration", "-of", "default=noprint_wrappers=1:nokey=1", videoPath)
output, err := cmd.Output()
if err != nil {
return 0, err
}
durationFloat, err := strconv.ParseFloat(strings.TrimSpace(string(output)), 64)
if err != nil {
return 0, err
}
duration := int(durationFloat)
return duration, nil
}
// 使用FFmpeg分割视频片段并去掉最后0.5秒
func splitVideoSegment(videoPath string, outputPath string, startTime int, duration int) error {
startTimeStr := strconv.Itoa(startTime)
durationStr := strconv.FormatFloat(float64(duration)-0.5, 'f', 1, 64) // 减去0.1秒
cmd := exec.Command("ffmpeg", "-ss", startTimeStr, "-i", videoPath, "-t", durationStr, "-c", "copy", outputPath)
err := cmd.Run()
if err != nil {
return err
}
return nil
}
// 合并视频
func mergeVideos(segments []string, outputPath string) error {
// 创建临时文件用于存储合并的视频文件列表
tempFile, err := ioutil.TempFile("", "video_segments.txt")
if err != nil {
return err
}
defer os.Remove(tempFile.Name())
// 写入视频文件路径到临时文件
for _, segment := range segments {
_, err := tempFile.WriteString(fmt.Sprintf("file '%s'\n", segment))
if err != nil {
return err
}
}
// 关闭临时文件
err = tempFile.Close()
if err != nil {
return err
}
// 执行 concat 操作合并视频
cmd := exec.Command("ffmpeg", "-f", "concat", "-safe", "0", "-i", tempFile.Name(), "-c", "copy", outputPath)
err = cmd.Run()
if err != nil {
return err
}
return nil
}
// 删除分割视频
func deleteSegmentFiles(segments []string) error {
for _, segment := range segments {
err := os.Remove(segment)
if err != nil {
return err
}
fmt.Printf("已删除分割视频: %s\n", segment)
}
return nil
}
文章来源:https://blog.csdn.net/qq_35583325/article/details/135067561
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!