GO语言实现视频分割

视频分割

每隔10秒分割一次,去掉分割视频的最后0.5秒,合并后删除分割视频

go 复制代码
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
}
相关推荐
大熊猫侯佩1 小时前
「内力探查术」:用 Instruments 勘破 SwiftUI 卡顿迷局
swiftui·debug·xcode
Magnetic_h3 小时前
【iOS】锁的原理
笔记·学习·macos·ios·objective-c·cocoa·xcode
眠りたいです3 小时前
Qt音频播放器项目实践:文件过滤、元数据提取与动态歌词显示实现
c++·qt·ui·音视频·媒体·qt5·mime
FreeDw资源库11 小时前
功能强大!开源免费的视频翻译、音视频转录工具
音视频·音视频翻译
七七&55612 小时前
2024年08月13日 Go生态洞察:Go 1.23 发布与全面深度解读
开发语言·网络·golang
java坤坤12 小时前
GoLand 项目从 0 到 1:第八天 ——GORM 命名策略陷阱与 Go 项目启动慢问题攻坚
开发语言·后端·golang
元清加油12 小时前
【Golang】:函数和包
服务器·开发语言·网络·后端·网络协议·golang
恋喵大鲤鱼15 小时前
Golang 后台技术面试套题 1
面试·golang
路多辛1 天前
Golang database/sql 包深度解析(二):连接池实现原理
数据库·sql·golang
kgduu1 天前
go资料汇总
golang