Convert .mp4 to gif using ffmpeg in golang - go

I want to convert my mp4 file to gif format. I was used the command that is working in command prompt. i.e., converting my .mp4 into gif but in go lang it is not done anything. Here is my command:
ffmpeg -i Untitled.mp4 -vf "fps=5,scale=320:-1:flags=lanczos" -c:v pam -f image2pipe - | convert -delay 5 - -loop 0 -layers optimize test.gif
I was used in go lang like this but it is not working. please any one help me to solve my problem.
cmd3 := exec.Command("ffmpeg", "-i", "Untitled.mp4", "-vf", "`fps=5,scale=320:-1:flags=lanczos`", "-c:v", "pam", "-f", "image2pipe", "- |", "convert", "-delay", "5", "-", "-loop", "0", "-layers", "optimize", "test.gif")
stdout2, err2 := cmd3.StdoutPipe()
log.Println("gif", stdout2)
if err2 != nil {
log.Fatal(err2, "............")
}
if err2 := cmd3.Start(); err2 != nil {
log.Fatal(err2)
}
if any changes is there please inform me thanks in advance.

This is not exactly what you are looking for, but it is possible to do it like this:
package main
import (
"fmt"
"os/exec"
)
func main() {
cmd := "ffmpeg -i Untitled.mp4 -vf \"fps=5,scale=320:-1:flags=lanczos\" -c:v pam -f image2pipe - | convert -delay 5 - -loop 0 -layers optimize test.gif"
_, err := exec.Command("bash","-c",cmd).Output()
if err != nil {
fmt.Println(fmt.Sprintf("Failed to execute command: %s", cmd))
}
}

Related

How to effectiv convert utf-8-mac to utf

I must convert regularly a file which contains uft-8-mac strings to uft-8. I started to do the job with iconv.
How ever iconv throws an error, if there was too many lines which must be converted.
Here is a script to reproduce the bug
#!/bin/zsh
set -eu
for i in {1..1000}; do
echo "$i:äöüß#€" >> /tmp/xx
iconv -f utf-8-mac -t utf-8 /tmp/xx > /dev/null
done
Obviously I can split the file, but I get then really a lot of files.
Has anyone another workaround or tool? Or a code example in golang?
I tried
func main() {
dat, err := os.ReadFile(".backup_files.unconv")
if err != nil {
log.Fatal(err)
}
output := ".backup_files.goconv"
w, err := os.Create(output)
if err != nil {
log.Fatalf("Can't create %s, %v", output, err)
}
defer closeFile(w)
wc := norm.NFC.Writer(w)
defer wc.Close()
wc.Write(dat)
}
But it differs from iconv result.
Thanks in advance.
Found an appropriate solution:
You can use the uconv utility from ICU. Normalization is achieved through transliteration (-x).
On Debian, Ubuntu and other derivatives, uconv is in the libicu-dev package. On Fedora, Red Hat and other derivatives, and in BSD ports, it's in the icu package.
Thanks to Gilles 'SO- stop being evil'

exec.Command error, no output to stdout or stderr

I am trying to get the duration of a video using ffprobe and exec.Command but I keep getting an error. However, stdout and stderr are both empty so I don't know what the problem is.
func getVideoLength(filename string) float64 {
cmd := exec.Command("ffprobe", "-i", filename, "-show_entries", "format=duration", "-v", "quiet", "-of", "csv=\"p=0\"")
fmt.Println("ffprobe", "-i", filename, "-show_entries", "format=duration", "-v", "quiet", "-of", "csv=\"p=0\"")
var out bytes.Buffer
var stderr bytes.Buffer
cmd.Stdout = &out
cmd.Stderr = &stderr
err := cmd.Run()
if err != nil {
fmt.Println("out: " + out.String())
fmt.Println("stderr: " + stderr.String())
log.Fatal(err)
}
length, err := strconv.ParseFloat(out.String(), 64)
if err != nil {
log.Fatal(err)
}
return length
}
Here is the output I get:
ffprobe -i amelie.mp4 -show_entries format=duration -v quiet -of csv="p=0"
out:
stderr:
2019/02/18 21:04:39 exit status 1
not very helpful.
Any ideas?. Thanks.
The reason you aren't getting any clues is that you have set the command to not say anything. From the ffprobe docs
-loglevel [flags+]loglevel | -v [flags+]loglevel Set logging level and flags used by the library.
....
loglevel is a string or a number containing one of the following
values:
‘quiet, -8’ Show nothing at all; be silent.

Running FFMPEG command through Golang exec

I need to run an ffmpeg command to create a video from images with a crossfade between images as the transition. The command is derived from this post. I need to run it through the Golang os/exec package. The command I need to run is:
ffmpeg -loop 1 -t 5 -i img-0.png -loop 1 -t 5 -i img-1.png -loop 1 -t 5 -i img-2.png -filter_complex "[1:v][0:v]blend=all_expr='A*(if(gte(T,0.5),1,T/0.5))+B*(1-(if(gte(T,0.5),1,T/0.5)))'[b1v];[2:v][1:v]blend=all_expr='A*(if(gte(T,0.5),1,T/0.5))+B*(1-(if(gte(T,0.5),1,T/0.5)))'[b2v];[0:v][b1v][1:v][b2v][2:v]concat=n=5:v=1:a=0,format=yuv420p[v]" -map '[v]' -c:v libx264 -pix_fmt yuv420p -r 30 -s 1280x720 -aspect 16:9 -crf 1 -preset ultrafast output.mp4
If you run this command directly in the terminal, it works just fine. However, it does not work through my code. This is my code that takes a string command and runs it through the os/exec package:
command := "ffmpeg -loop 1 -t 5 -i img-0.png -loop 1 -t 5 -i img-1.png -loop 1 -t 5 -i img-2.png -filter_complex "[1:v][0:v]blend=all_expr='A*(if(gte(T,0.5),1,T/0.5))+B*(1-(if(gte(T,0.5),1,T/0.5)))'[b1v];[2:v][1:v]blend=all_expr='A*(if(gte(T,0.5),1,T/0.5))+B*(1-(if(gte(T,0.5),1,T/0.5)))'[b2v];[0:v][b1v][1:v][b2v][2:v]concat=n=5:v=1:a=0,format=yuv420p[v]" -map '[v]' -c:v libx264 -pix_fmt yuv420p -r 30 -s 1280x720 -aspect 16:9 -crf 1 -preset ultrafast output.mp4"
lastQuote := rune(0)
f := func(c rune) bool {
switch {
case c == lastQuote:
lastQuote = rune(0)
return false
case lastQuote != rune(0):
return false
case unicode.In(c, unicode.Quotation_Mark):
lastQuote = c
return false
default:
return unicode.IsSpace(c)
}
}
parts := strings.FieldsFunc(command, f)
cmd := exec.Command(parts[0], parts[1:]...)
cmd.Stderr = os.Stderr
cmd.Stdout = os.Stdout
err := cmd.Run()
if err != nil {
return err
}
When I run this, I get the ffmpeg error: No such filter: '"', Error configuring filters. I know it has something to do with the quotes that HAVE to be in the video filters, but I have tried everything to get it to work and I can't figure it out.
Any help is greatly appreciated!
This actually does work correctly :
exec.Command("ffmpeg", "-loop", "1", "-t", "5", "-i", "img-0.png", "-loop", "1", "-t", "5", "-i", "img-1.png", "-loop", "1", "-t", "5", "-i", "img-2.png", "-filter_complex", "[1:v][0:v]blend=all_expr='A*(if(gte(T,0.5),1,T/0.5))+B*(1-(if(gte(T,0.5),1,T/0.5)))'[b1v];[2:v][1:v]blend=all_expr='A*(if(gte(T,0.5),1,T/0.5))+B*(1-(if(gte(T,0.5),1,T/0.5)))'[b2v];[0:v][b1v][1:v][b2v][2:v]concat=n=5:v=1:a=0,format=yuv420p[v]", "-map", "[v]", "-c:v", "libx264", "-pix_fmt", "yuv420p", "-r", "30", "-s", "1280x720", "-aspect", "16:9", "-crf", "1", "-preset", "ultrafast", "output.mp4")
Notice that I did remove start and end double quotes from the -filter_complex parameters and two single quotes from the -map parameters.
Did it by hand, though, not sure of a strings function that could do it automagically.

Installing virtual Machine with virt-install

virt-install \
-n "NAME" \
-r 1024 \
--import \
--disk path="1703_Disk.img" \
--accelerate \
--network network=default \
--connect=qemu:///system \
--vnc \
-v
Can someone explain me how to execute this in Go.
The os/exec package is what you're looking for:
cmdName := "virt-install"
args := []string{
"-n", "NAME",
"-r", "1024",
"--import",
"--disk", "path=1703_Disk.img"
"--accelerate",
"--network", "network=default",
"--connect=qemu:///system",
"-vnc",
"-v",
}
cmd := exec.Command(cmdName, args...)
if err := cmd.Start(); err != nil {
log.Fatal(err)
}
if err := cmd.Wait(); err != nil {
log.Fatal(err)
}
There is a Go API for libvirt, either the one at https://gitlab.com/libvirt/libvirt-go-module or the https://github.com/digitalocean/go-libvirt one. For some tasks, it makes more sense to use that, instead of running libvirt commands as a subprocess.
The virt-install case probably makes most sense as a subprocess, however.

Golang + Avconv error (exit status 254)

I'm getting "panic: exit status 254" on the second line.
Can you spot the mistake I made here:
command := exec.Command("avprobe", "inputfile.mp4 -loglevel quiet -show_streams -frame_size -print_format -show_format -of json")
output, err := command.StdoutPipe();
if err != nil {
log.Panic(err)
}
if err := command.Run(); err != nil {
log.Panic(err)
}
json.NewDecoder(output).Decode(&struct1)
You are running the equivalent of
avprobe "inputfile.mp4 -loglevel quiet -show_streams -frame_size -print_format -show_format -of json"
I am guessing avprobe doesn't like that, try
command := exec.Command("avprobe", "inputfile.mp4", "-loglevel", ...)
You can also use exec.CombinedOutput() to get the output from avprobe and see what it says.
Package exec
func Command
func Command(name string, arg ...string) *Cmd
For example,
arg := []string{
"inputfile.mp4",
"-loglevel", "quiet",
"-show_streams",
"-frame_size",
"-print_format",
"-show_format",
"-of", "json",
}
command := exec.Command("avprobe", arg...)

Resources