Maison >développement back-end >Golang >transcodage ffmpeg golang
À mesure que la vidéo est de plus en plus utilisée dans les médias modernes, de nombreuses applications nécessitent un transcodage vidéo entre différentes plates-formes et appareils. Ce faisant, FFmpeg et Golang sont devenus les outils de transcodage de choix pour de nombreux développeurs. Cet article présentera les concepts de base et l'utilisation de FFmpeg et Golang, et comment les combiner pour un transcodage vidéo efficace.
Introduction à FFmpeg
FFmpeg est une bibliothèque de codecs vidéo et audio multiplateforme open source qui peut être utilisée pour traiter divers formats vidéo. Il fournit un outil en ligne de commande qui permet aux développeurs d'utiliser directement ses fonctionnalités telles que la conversion de format, le découpage vidéo, le transcodage en temps réel, etc.
Introduction à Golang
Golang est un langage de programmation moderne, développé pour la première fois par Google et open source. Il est largement considéré comme un langage de programmation efficace, simple et sécurisé, particulièrement adapté à une utilisation dans les applications de réseau et de cloud computing.
FFmpeg et Golang combinés
Golang peut utiliser la technologie CGO pour appeler les bibliothèques de langage C, ce qui facilite l'utilisation des fonctions de FFmpeg. En utilisant l'outil de ligne de commande de FFmpeg, nous pouvons facilement transcoder des vidéos vers différents formats tels que mp4, webm, etc.
Cependant, en appelant directement l'outil de ligne de commande FFmpeg, vous devez créer un processus enfant, puis attendre que le processus enfant se termine pour obtenir les résultats. Cette méthode est inefficace et n'est pas propice à l'expansion et à la maintenance du programme.
Par conséquent, Golang fournit un outil appelé cgo pour nous permettre d'utiliser facilement du code C dans les programmes Golang, puis d'utiliser facilement les fonctions de FFmpeg. Dans l'exemple suivant, nous montrerons comment encapsuler les fonctions de FFmpeg via la technologie cgo.
Tout d'abord, nous devons définir une structure en Golang pour représenter le type AVFrame dans FFmpeg.
type AVFrame struct { data [8]*uint8 linesize [8]int32 best_effort_timestamp int64 pkt_pts int64 }
Ensuite, nous devons définir certaines interfaces de fonctions C pour appeler les fonctions FFmpeg. Par exemple, nous pouvons définir une fonction pour ouvrir un fichier audio ou vidéo :
// #cgo LDFLAGS: -lavformat -lavcodec -lavutil // #include <libavformat/avformat.h> // #include <libavcodec/avcodec.h> // #include <libavutil/avutil.h> import "C" func av_open_input_file(pFormatContext **C.AVFormatContext, filename string, fmt *C.AVInputFormat, buf_size int, pFormatParams **C.AVFormatParameters) int { cfilename := C.CString(filename) defer C.free(unsafe.Pointer(cfilename)) result := C.av_open_input_file(pFormatContext, cfilename, fmt, C.int(buf_size), pFormatParams) return int(result) }
Dans le code ci-dessus, nous utilisons la directive de commentaire #cgo LDFLAGS pour indiquer au compilateur Golang qu'il doit lier le fichier de la bibliothèque FFmpeg. Dans le même temps, nous utilisons également le type unsafe.Pointer fourni par CGO pour transmettre des objets pointeur au code C.
Bien entendu, afin d'utiliser d'autres fonctions fournies par FFmpeg, d'autres interfaces de fonctions C doivent être définies. Pour simplifier l'introduction de l'exemple, seule une fonction d'interface simple est répertoriée ici.
Une fois que nous avons défini ces fonctions d'interface, nous pouvons facilement utiliser ces fonctions d'interface dans le code Golang pour profiter des diverses fonctions de FFmpeg.
Par exemple, nous pouvons utiliser le code suivant pour convertir un fichier audio au format WAV au format mp3 :
func main() { var pFormatContext *C.AVFormatContext var inputFormat *C.AVInputFormat var formatParams *C.AVFormatParameters filename := "input.wav" if ret := av_open_input_file(&pFormatContext, filename, inputFormat, 0, &formatParams); ret != 0 { log.Fatalf("Could not open input file %s, error code=%d ", filename, ret) } if ret := C.avformat_find_stream_info(pFormatContext, nil); ret < 0 { log.Fatalf("Could not find stream info, error code=%d ", ret) } audioStreamIndex := -1 for i := 0; i < int(pFormatContext.nb_streams); i++ { st := (*C.AVStream)(unsafe.Pointer(uintptr(unsafe.Pointer(pFormatContext.streams)) + uintptr(i)*unsafe.Sizeof(*pFormatContext.streams))) if st.codec.codec_type == C.AVMEDIA_TYPE_AUDIO { audioStreamIndex = i break } } if audioStreamIndex == -1 { log.Fatalf("Could not find audio stream ") } audioStream := (*C.AVStream)(unsafe.Pointer(uintptr(unsafe.Pointer(pFormatContext.streams)) + uintptr(audioStreamIndex)*unsafe.Sizeof(*pFormatContext.streams))) audioCodecContext := (*C.AVCodecContext)(unsafe.Pointer(audioStream.codec)) audioCodec := C.avcodec_find_decoder(audioCodecContext.codec_id) if audioCodec == nil { log.Fatalf("Unsupported codec type, codec_id=%d ", audioCodecContext.codec_id) } if ret := C.avcodec_open2(audioCodecContext, audioCodec, nil); ret < 0 { log.Fatalf("Could not open audio codec, error code=%d ", ret) } tempFilePath := "temp.raw" tempFile, _ := os.Create(tempFilePath) defer tempFile.Close() defer os.Remove(tempFilePath) packet := (*C.AVPacket)(C.malloc(C.sizeof_AVPacket)) defer C.free(unsafe.Pointer(packet)) frame := (*C.AVFrame)(C.avcodec_alloc_frame()) defer C.av_free(unsafe.Pointer(frame)) for { if ret := C.av_read_frame(pFormatContext, packet); ret < 0 { break } if packet.stream_index == C.int(audioStreamIndex) { if ret := C.avcodec_decode_audio4(audioCodecContext, frame, (*C.int)(nil), packet); ret > 0 { numSamples := int(frame.nb_samples) dataPtr := uintptr(unsafe.Pointer(frame.data[0])) dataSlice := (*[1 << 30]byte)(unsafe.Pointer(dataPtr)) dataSize := numSamples * int(audioCodecContext.channels) * int(C.av_get_bytes_per_sample(audioCodecContext.sample_fmt)) tempFile.Write(dataSlice[:dataSize]) } } C.av_free_packet(packet) } tempFile.Close() outputFilePath := "output.mp3" cmd := exec.Command("ffmpeg", "-y", "-f", "s16le", "-ar", strconv.Itoa(int(audioCodecContext.sample_rate)), "-ac", strconv.Itoa(int(audioCodecContext.channels)), "-i", tempFilePath, "-f", "mp3", outputFilePath) stdout, _ := cmd.StdoutPipe() cmd.Start() for { buf := make([]byte, 1024) n, err := stdout.Read(buf) if err != nil || n == 0 { break } } cmd.Wait() }
Dans l'exemple ci-dessus, nous utilisons d'abord la fonction av_open_input_file pour ouvrir le fichier audio, puis utilisons la fonction avformat_find_stream_info pour obtenir les informations sur le flux audio.
Ensuite, nous parcourons tous les flux pour trouver le flux audio et ouvrons le décodeur audio à l'aide de la fonction avcodec_open2. Après cela, nous utilisons la fonction av_read_frame pour lire les données audio image par image et écrire les données audio dans un fichier temporaire.
Enfin, nous utilisons l'outil de ligne de commande FFmpeg pour convertir les données audio du fichier temporaire en un fichier audio au format mp3.
Conclusion
En combinant Golang et FFmpeg, nous pouvons facilement implémenter un programme de transcodage vidéo efficace et utiliser la syntaxe élégante et les fonctions intégrées de Golang. Même si l’utilisation de la technologie cgo peut nécessiter une certaine connaissance du langage C, elle n’est pas difficile à mettre en œuvre et les résultats sont significatifs. Si vous avez besoin de hautes performances et de portabilité lors du développement d'un programme de transcodage vidéo, la combinaison de Golang et FFmpeg peut être un bon choix.
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!