
Recherche avancée
Médias (2)
-
GetID3 - Bloc informations de fichiers
9 avril 2013, par
Mis à jour : Mai 2013
Langue : français
Type : Image
-
GetID3 - Boutons supplémentaires
9 avril 2013, par
Mis à jour : Avril 2013
Langue : français
Type : Image
Autres articles (61)
-
Librairies et logiciels spécifiques aux médias
10 décembre 2010, parPour un fonctionnement correct et optimal, plusieurs choses sont à prendre en considération.
Il est important, après avoir installé apache2, mysql et php5, d’installer d’autres logiciels nécessaires dont les installations sont décrites dans les liens afférants. Un ensemble de librairies multimedias (x264, libtheora, libvpx) utilisées pour l’encodage et le décodage des vidéos et sons afin de supporter le plus grand nombre de fichiers possibles. Cf. : ce tutoriel ; FFMpeg avec le maximum de décodeurs et (...) -
Publier sur MédiaSpip
13 juin 2013Puis-je poster des contenus à partir d’une tablette Ipad ?
Oui, si votre Médiaspip installé est à la version 0.2 ou supérieure. Contacter au besoin l’administrateur de votre MédiaSpip pour le savoir -
Les tâches Cron régulières de la ferme
1er décembre 2010, parLa gestion de la ferme passe par l’exécution à intervalle régulier de plusieurs tâches répétitives dites Cron.
Le super Cron (gestion_mutu_super_cron)
Cette tâche, planifiée chaque minute, a pour simple effet d’appeler le Cron de l’ensemble des instances de la mutualisation régulièrement. Couplée avec un Cron système sur le site central de la mutualisation, cela permet de simplement générer des visites régulières sur les différents sites et éviter que les tâches des sites peu visités soient trop (...)
Sur d’autres sites (12554)
-
ffprobe different results video duration using pipe and reading a file from the file system
5 février 2024, par alexI have a method to convert a video file, after processing the file I use
pipe
to pass bytes to a method to get meta information about the file using pipe. But in this case I get wrongduration
of video file, 8.22, but if I save the file on file system and read it to get meta information I get result 15.85. Why is this happening ?

Video Convert method :


// ConvertVideoWithPath converts a video file specified by its path using FFmpeg.
// It returns the converted video data and any error that occurred during conversion.
func (f *FFmpeg) ConvertVideoWithPath(filePath string) (bytes []byte, err error) {
 if filePath == "" {
 return nil, ErrEmptyPath
 }

 // Create a CmdRunner instance for executing FFmpeg.
 commander := &CmdRunner{}
 commander.Command = "ffmpeg"
 args := []string{
 "-loglevel", "fatal",
 "-i", filePath,
 "-y",
 "-filter:v", "crop=trunc(iw/2)*2:trunc(ih/2)*2",
 "-c:v", f.videoCodec, // libx264
 "-c:a", f.audioCodec, // aac
 "-pix_fmt", "yuv420p",
 "-movflags", "frag_keyframe+faststart",
 "-map_metadata", "-1",
 "-crf", "5",
 "-vsync", "2",
 "-bufsize", "15000000",
 "-maxrate", "5000000",
 "-preset", "medium",
 "-f", "mp4",
 "pipe:1",
 }
 commander.Args = args

 // Initialize output pipe.
 reader := commander.InitStdOutPipe()

 // Use WaitGroup to synchronize goroutines.
 wg := &sync.WaitGroup{}
 wg.Add(1)

 // Goroutine for reading data from the output pipe.
 go func() {
 defer reader.Close()
 defer wg.Done()

 // Read data from the output pipe.
 data, _ := io.ReadAll(reader)
 // Safely update the 'bytes' variable.
 f.mutex.Lock()
 bytes = data
 f.mutex.Unlock()
 }()

 // Run the FFmpeg command with pipes and wait for completion.
 err = <-commander.RunWithPipe()
 wg.Wait()

 return
}



// MetadataWithReader retrieves metadata from media data provided by an io.Reader using FFprobe.
// It returns the metadata and any error that occurred during metadata retrieval.
func (f *FFmpeg) MetadataWithReader(fileBytes io.Reader) (*Metadata, error) {
 if fileBytes == nil {
 return nil, ErrInvalidArgument
 }

 // Create a CmdRunner instance for executing FFprobe.
 commander := &CmdRunner{}
 commander.Command = "ffprobe"
 args := []string{
 "-loglevel", "fatal",
 "-i", "pipe:0",
 "-print_format", "json",
 "-show_format", "-show_streams",
 "-show_error",
 }
 commander.Args = args

 // Get output data from FFprobe with pipes.
 err := commander.GetOutputWithPipe(fileBytes)
 if err != nil {
 return nil, err
 }

 // Unmarshal JSON output into a Metadata struct.
 output := &Metadata{}
 err = json.Unmarshal(commander.GetOutput(), output)
 if err != nil {
 return nil, err
 }

 return output, err
}



// MetadataWithPath extracts metadata of a file using FFprobe.
// It returns a Metadata struct or an error if the operation fails.
func (f *FFmpeg) MetadataWithPath(filePath string) (*Metadata, error) {
 if filePath == "" {
 return nil, ErrEmptyPath
 }

 // Create a CmdRunner instance for executing FFprobe.
 commander := &CmdRunner{}
 commander.Command = "ffprobe"
 args := []string{
 "-loglevel", "fatal",
 "-i", filePath,
 "-loglevel",
 "fatal",
 "-print_format", "json",
 "-show_format", "-show_streams", "-show_error",
 }
 commander.Args = args
 buffer := bytes.NewBuffer([]byte{})
 commander.StdOutWriter = buffer

 err := commander.Run()
 if err != nil {
 return nil, err
 }

 // Unmarshal JSON output into a Metadata struct.
 output := &Metadata{}
 err = json.Unmarshal(buffer.Bytes(), output)
 if err != nil {
 return nil, err
 }

 return output, nil
}



The source code of the
CmdRunner
biblio library can be found here link , so as not to overload the question with a large piece of code.

Unit test code


t.Run("convert video", func(t *testing.T) {
 ffmpeg := NewFFmpeg("aac", "libx264", "24M", "12M")

 filePath := "../../test/testdata/input_video_ts.mp4"
 firstMeta, err := ffmpeg.MetadataWithPath(filePath)
 assert.NoError(t, err)
 fmt.Print("first meta duration: ", firstMeta.Format.DurationSeconds) // 15.75

 outFile := "../../test/testdata/output_mp4.mp4"
 newVideoOut, err := ffmpeg.ConvertVideoWithPath(filePath)
 assert.NoError(t, err)
 assert.NotEmpty(t, newVideoOut)

 meta, err := ffmpeg.MetadataWithReader(bytes.NewBuffer(newVideoOut))
 assert.NoError(t, err)
 assert.NotEmpty(t, meta)

 err = os.WriteFile(outFile, newVideoOut, 0644)
 assert.NoError(t, err)
 assert.FileExists(t, outFile)

 fmt.Print("meta duration: ", meta.Format.DurationSeconds) // 8.22

 secondMeta, err := ffmpeg.MetadataWithPath(outFile)
 assert.NoError(t, err)
 fmt.Print("second meta duration: ", secondMeta.Format.DurationSeconds) //15.85

 err = os.Remove(outFile)
 assert.NoError(t, err)
 })



-
Saving a continuous stream of images from ffmpeg image2pipe
11 février 2020, par MinaI am trying to save a sequence/continuous images from ffmpeg image2pipe in go. The problem with the code below that it does only save the first image in the stream due to the blocking nature of io.Copy since it waits for the reader or the writer to close.
package main
import (
"fmt"
"io"
"log"
"os"
"os/exec"
"strconv"
"time"
)
//Trying to get png from stdout pipe
func main() {
fmt.Println("Running the camera stream")
ffmpegCmd := exec.Command("ffmpeg", "-loglevel", "quiet", "-y", "-rtsp_transport", "tcp", "-i", "rtsp://admin:123456@192.168.1.41:554/h264Preview_01_main", "-r", "1", "-f", "image2pipe", "pipe:1")
ffmpegOut, err := ffmpegCmd.StdoutPipe()
if err != nil {
return
}
err = ffmpegCmd.Start()
if err != nil {
log.Fatal(err)
}
count := 0
for {
count++
t := time.Now()
fmt.Println("writing image" + strconv.Itoa(count))
filepath := "image-" + strconv.Itoa(count) + "-" + t.Format("20060102150405.png")
out, err := os.Create(filepath)
if err != nil {
log.Fatal(err)
}
defer out.Close()
_, err = io.Copy(out, ffmpegOut)
if err != nil {
log.Fatalf("unable to copy to file: %s", err.Error())
}
}
if err := ffmpegCmd.Wait(); err != nil {
log.Fatal("Error while waiting:", err)
}
}I implemented my own save and copy function based on the io.Copy code https://golang.org/src/io/io.go
func copyAndSave(w io.Writer, r io.Reader) error {
buf := make([]byte, 1024, 1024)
for {
n, err := r.Read(buf[:])
if n == 0 {
}
if n > 0 {
d := buf[:n]
_, err := w.Write(d)
if err != nil {
return err
}
}
if err != nil {
return err
}
}
return nil
}then I updated the for loop in my main function to the below block but still I am only getting the first image in the sequence. due to
r.Read(buf[:])
is being a blocking call.for {
count++
t := time.Now()
fmt.Println("writing image" + strconv.Itoa(count))
filepath := "image-" + strconv.Itoa(count) + "-" + t.Format("20060102150405.png")
out, err := os.Create(filepath)
if err != nil {
log.Fatal(err)
}
defer out.Close()
err = copyAndSave(out, ffmpegOut)
if err != nil {
if err == io.EOF {
break
}
log.Fatalf("unable to copy to file: %s", err.Error())
break
}
} -
Read PCM data from a compressed file in GridFS
14 août 2012, par user1599160I need to get a iterable of pcm frames from a file in GridFs.
I think the problem can be reduced to first reading the whole file from gridfs to memory and then decoding that to PCM.
I have read up on using subprocess and pipes with ffmpeg, and there is a project called audio-reader that does this but with file arguments to ffmpeg, not with audio data from memory.
There is a library called pymedia but it is from 2006 and only works with outdated ffmpeg.
How should I proceed, also if you are going to sugest ffmpeg with subprocess and pipes, please give me some example code, maybe it is just late, but I finding the python docs on subprocess confusing...