Maison >développement back-end >Golang >Comment utiliser le langage Go pour le traitement audio et vidéo ?

Comment utiliser le langage Go pour le traitement audio et vidéo ?

WBOY
WBOYoriginal
2023-06-10 12:07:542820parcourir

Ces dernières années, avec le développement de la technologie audio et vidéo, la demande de technologies liées au traitement audio et vidéo est devenue de plus en plus élevée. En tant que langage de programmation hautes performances, Go fournit également de nombreux outils et bibliothèques pratiques pour faciliter le traitement des données audio et vidéo. Cet article présentera comment utiliser le langage Go pour le traitement audio et vidéo. Le contenu spécifique est le suivant :

1. Comment utiliser Go pour traiter l'audio

Dans le langage Go, le traitement des données audio nécessite généralement l'utilisation d'un. bibliothèque de codecs audio. Actuellement, les plus couramment utilisés incluent portaudio et ffmpeg. Ici, nous prenons ffmpeg comme exemple et donnons un exemple de code simple pour lire des fichiers audio, convertir des formats et enregistrer :

package main

import (
    "github.com/giorgisio/goav/avcodec"
    "github.com/giorgisio/goav/avformat"
    "github.com/giorgisio/goav/avutil"
    "log"
)

func main() {
    // 打开输入文件
    inputCtx := avformat.AvformatAllocContext()
    if err := avformat.AvformatOpenInput(&inputCtx, "input.mp3", nil, nil); err != nil {
        log.Fatal(err)
    }
    defer avformat.AvformatCloseInput(inputCtx)

    // 查找音频流
    if err := avformat.AvformatFindStreamInfo(inputCtx, nil); err != nil {
        log.Fatal(err)
    }
    audioIndex := -1
    for i := 0; i < int(inputCtx.NbStreams()); i++ {
        codecCtx := inputCtx.Streams()[i].Codec()
        if codecCtx.CodecType() == avutil.AVMEDIA_TYPE_AUDIO {
            audioIndex = i
            break
        }
    }
    if audioIndex < 0 {
        log.Fatal("No audio stream found")
    }

    // 打开解码器
    codecCtx := inputCtx.Streams()[audioIndex].Codec()
    codec := avcodec.AvcodecFindDecoder(codecCtx.CodecId())
    if codec == nil {
        log.Fatal("Unsupported codec")
    }
    if err := codecCtx.AvcodecOpen2(codec, nil); err != nil {
        log.Fatal(err)
    }
    defer codecCtx.AvcodecClose()

    // 打开输出文件
    outputFmt := avformat.AvGuessFormat("wav", "output.wav", "")
    if outputFmt == nil {
        log.Fatal("Failed to guess output format")
    }
    outputCtx := avformat.AvformatAllocContext()
    outputCtx.SetOutputFormat(outputFmt)
    if err := avformat.AvioOpen(outputCtx.Pb(), "output.wav", avformat.AVIO_FLAG_WRITE); err != nil {
        log.Fatal(err)
    }

    // 写入输出头
    if err := avformat.AvformatWriteHeader(outputCtx, nil); err != nil {
        log.Fatal(err)
    }

    // 读取、解码和转换音频帧
    for {
        pkt := avcodec.AvPacketAlloc()
        defer avutil.AvPacketFree(pkt)
        if ret := avformat.AvReadFrame(inputCtx, pkt); ret < 0 {
            if ret == avutil.AVERROR_EOF || ret == avutil.ErrEAGAIN {
                break
            }
            log.Fatal(ret)
        }
        if pkt.StreamIndex() != audioIndex {
            continue
        }
        frame := avutil.AvFrameAlloc()
        defer avutil.AvFrameFree(frame)
        if _, gotframe, ret := codecCtx.AvcodecDecodeAudio4(pkt, frame); ret >= 0 && gotframe {
            // 转换格式
            if _, _, ret := codecCtx.AvcodecSendPacket(pkt); ret < 0 {
                log.Fatal(ret)
            }
            for {
                frame2 := avutil.AvFrameAlloc()
                if _, ret := codecCtx.AvcodecReceiveFrame(frame2); ret == avutil.AvErrorEOF {
                    break
                } else if ret < 0 {
                    log.Fatal(ret)
                }
                if _, ret := avcodec.AvAudioResample(frame2, frame, avformat.AV_SAMPLE_FMT_S16, int(codecCtx.SampleRate()), avformat.AV_SAMPLE_FMT_FLTP, int(codecCtx.SampleRate()), 0, 0); ret < 0 {
                    log.Fatal(ret)
                }

                // 写入输出帧
                if _, ret := avformat.AvInterleavedWriteFrame(outputCtx, frame); ret != nil {
                    log.Fatal(ret)
                }
            }
        }
    }

    // 写入输出尾
    if err := avformat.AvWriteTrailer(outputCtx); err != nil {
        log.Fatal(err)
    }
}

Explication du code :

  1. Lire les fichiers d'entrée

Utilisez avformat.AvformatOpenInput ici Le La fonction ouvre le fichier d'entrée et trouve le flux audio à l'aide de avformat.AvformatFindStreamInfo. avformat.AvformatOpenInput 函数打开输入文件,并使用 avformat.AvformatFindStreamInfo 查找音频流。

  1. 打开解码器

在代码中使用 avcodec.AvcodecFindDecoder 函数来查找支持的解码器并打开它,这里假设输入文件的编码格式合法。

  1. 打开输出文件

使用 avformat.AvGuessFormat 找出输出文件的编码格式,然后使用 avformat.AvformatAllocContext 函数创建输出文件上下文并打开文件。

  1. 读取、解码和转换音频帧

使用 avformat.AvReadFrame 函数从输入文件中读取帧,并检查它是否属于音频流。如果是,则使用解码器将帧解码为音频数据。然后再使用 avcodec.AvAudioResample 函数将音频数据转换为设定的采样率和格式。最后,使用 avformat.AvInterleavedWriteFrame 函数将输出帧写入输出文件。

  1. 最后,关闭输入和输出文件。

二、如何使用 Go 处理视频

在 Go 语言中处理视频数据同样需要使用视频编解码库,同样可以使用 ffmpeg 这个工具库。接下来给出一个简单的读取视频文件、提取帧和保存的示例代码:

package main

import (
    "github.com/giorgisio/goav/avcodec"
    "github.com/giorgisio/goav/avformat"
    "github.com/giorgisio/goav/avutil"
    "image"
    "os"
)

func main() {
    // 打开输入文件
    inputCtx := avformat.AvformatAllocContext()
    if err := avformat.AvformatOpenInput(&inputCtx, "input.mp4", nil, nil); err != nil {
        panic(err)
    }
    defer avformat.AvformatCloseInput(inputCtx)

    // 查找视频流
    if err := avformat.AvformatFindStreamInfo(inputCtx, nil); err != nil {
        panic(err)
    }
    videoIndex := -1
    for i := 0; i < int(inputCtx.NbStreams()); i++ {
        codecCtx := inputCtx.Streams()[i].Codec()
        if codecCtx.CodecType() == avutil.AVMEDIA_TYPE_VIDEO {
            videoIndex = i
            break
        }
    }
    if videoIndex < 0 {
        panic("No video stream found")
    }

    // 打开解码器
    codecCtx := inputCtx.Streams()[videoIndex].Codec()
    codec := avcodec.AvcodecFindDecoder(codecCtx.CodecId())
    if codec == nil {
        panic("Unsupported codec")
    }
    if err := codecCtx.AvcodecOpen2(codec, nil); err != nil {
        panic(err)
    }
    defer codecCtx.AvcodecClose()

    // 创建输出文件
    output, err := os.Create("output.jpg")
    if err != nil {
        panic(err)
    }
    defer output.Close()

    // 提取视频帧
    packet := avutil.AvPacketAlloc()
    defer avutil.AvPacketFree(packet)
    for {
        if ret := avformat.AvReadFrame(inputCtx, packet); ret < 0 {
            if ret == avutil.AVERROR_EOF || ret == avutil.ErrEAGAIN {
                break
            }
            panic(ret)
        }
        if packet.StreamIndex() != videoIndex {
            continue
        }

        // 解码视频帧
        frame := avutil.AvFrameAlloc()
        defer avutil.AvFrameFree(frame)
        if gotframe, ret := codecCtx.AvcodecSendPacket(packet); ret >= 0 && gotframe {
            for {
                frame := avutil.AvFrameAlloc()
                if _, ret := codecCtx.AvcodecReceiveFrame(frame); ret == avutil.AvErrorEOF {
                    break
                } else if ret < 0 {
                    panic(ret)
                }

                // 写入输出文件
                img := image.NewRGBA(image.Rect(0, 0, int(frame.Width()), int(frame.Height())))
                for y := 0; y < int(frame.Height()); y++ {
                    for x := 0; x < int(frame.Width()); x++ {
                        c := frame.Data(0)[y*frame.Linesize(0)+x*3 : y*frame.Linesize(0)+x*3+3]
                        img.SetRGBA(x, y, color.RGBA{c[0], c[1], c[2], 255})
                    }
                }
                if err := jpeg.Encode(output, img, &jpeg.Options{Quality: 100}); err != nil {
                    panic(err)
                }
                break
            }
        }
    }
}

代码解释:

  1. 读取输入文件

同样是使用 avformat.AvformatOpenInput 函数打开输入文件,并使用 avformat.AvformatFindStreamInfo 查找视频流。

  1. 打开解码器

在代码中同样使用 avcodec.AvcodecFindDecoder 函数来查找支持的解码器并打开它,这里假设输入文件的编码格式合法。

  1. 创建输出文件

使用 Go 内置的 os 包创建输出文件并打开。

  1. 提取视频帧

使用 avformat.AvReadFrame

    Ouvrez le décodeur
    1. Utilisez la fonction avcodec.AvcodecFindDecoder dans le code pour trouver le décodeur pris en charge et ouvrez-le. Il est supposé que le format d'encodage du. le fichier d’entrée est légal.

      Ouvrez le fichier de sortie

      Utilisez avformat.AvGuessFormat pour connaître le format d'encodage du fichier de sortie, puis utilisez le avformat.AvformatAllocContext code> pour créer le contexte du fichier de sortie et ouvrir le fichier. 🎜<ol start="4">🎜Lire, décoder et convertir des images audio 🎜🎜🎜Utilisez la fonction <code>avformat.AvReadFrame pour lire une image du fichier d'entrée et vérifier si elle appartient au flux audio . Si tel est le cas, utilisez un décodeur pour décoder la trame en données audio. Utilisez ensuite la fonction avcodec.AvAudioResample pour convertir les données audio au taux d'échantillonnage et au format définis. Enfin, utilisez la fonction avformat.AvInterleavedWriteFrame pour écrire le cadre de sortie dans le fichier de sortie. 🎜🎜🎜Enfin, fermez les fichiers d'entrée et de sortie. 🎜🎜🎜2. Comment utiliser Go pour traiter la vidéo🎜🎜Le traitement des données vidéo en langage Go nécessite également l'utilisation d'une bibliothèque de codecs vidéo, et vous pouvez également utiliser la bibliothèque d'outils ffmpeg. Ensuite, un exemple de code simple pour lire un fichier vidéo, extraire des images et enregistrer est donné : 🎜rrreee🎜Explication du code : 🎜🎜🎜Lire le fichier d'entrée🎜🎜🎜en utilisant également la fonction avformat.AvformatOpenInput Ouvrir le fichier d'entrée et utilisez avformat.AvformatFindStreamInfo pour trouver le flux vidéo. 🎜
        🎜Ouvrez le décodeur🎜🎜🎜Utilisez également la fonction avcodec.AvcodecFindDecoder dans le code pour trouver le décodeur pris en charge et ouvrez-le. Il est supposé que le format d'encodage de. le fichier d'entrée est légal. 🎜
          🎜Créer un fichier de sortie🎜🎜🎜Utilisez le package OS intégré de Go pour créer un fichier de sortie et l'ouvrir. 🎜
            🎜Extraire les images vidéo🎜🎜🎜Utilisez la fonction avformat.AvReadFrame pour lire l'image du fichier d'entrée et vérifier si elle appartient au flux vidéo. Si tel est le cas, utilisez un décodeur pour décoder l'image en données vidéo. Les données vidéo sont ensuite converties en données d'image (ici au format JPEG) via une boucle et écrites dans le fichier de sortie. 🎜🎜🎜Enfin, fermez les fichiers d'entrée et de sortie. 🎜🎜🎜Résumé🎜🎜Cet article présente comment utiliser le langage Go pour traiter les données audio et vidéo. L'analyse, l'encodage et le décodage des formats sont des maillons clés du traitement audio et vidéo. Ici, nous utilisons la bibliothèque d'outils ffmpeg pour traiter les formats audio et vidéo. Dans les applications réelles, des opérations de traitement audio et vidéo plus complexes peuvent être nécessaires, mais le cadre global du code est similaire. Nous espérons que notre exemple de code pourra vous aider pour votre travail de traitement audio et vidéo. 🎜

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn