
Recherche avancée
Médias (91)
-
Spoon - Revenge !
15 septembre 2011, par
Mis à jour : Septembre 2011
Langue : English
Type : Audio
-
My Morning Jacket - One Big Holiday
15 septembre 2011, par
Mis à jour : Septembre 2011
Langue : English
Type : Audio
-
Zap Mama - Wadidyusay ?
15 septembre 2011, par
Mis à jour : Septembre 2011
Langue : English
Type : Audio
-
David Byrne - My Fair Lady
15 septembre 2011, par
Mis à jour : Septembre 2011
Langue : English
Type : Audio
-
Beastie Boys - Now Get Busy
15 septembre 2011, par
Mis à jour : Septembre 2011
Langue : English
Type : Audio
-
Granite de l’Aber Ildut
9 septembre 2011, par
Mis à jour : Septembre 2011
Langue : français
Type : Texte
Autres articles (11)
-
Soumettre améliorations et plugins supplémentaires
10 avril 2011Si vous avez développé une nouvelle extension permettant d’ajouter une ou plusieurs fonctionnalités utiles à MediaSPIP, faites le nous savoir et son intégration dans la distribution officielle sera envisagée.
Vous pouvez utiliser la liste de discussion de développement afin de le faire savoir ou demander de l’aide quant à la réalisation de ce plugin. MediaSPIP étant basé sur SPIP, il est également possible d’utiliser le liste de discussion SPIP-zone de SPIP pour (...) -
MediaSPIP version 0.1 Beta
16 avril 2011, parMediaSPIP 0.1 beta est la première version de MediaSPIP décrétée comme "utilisable".
Le fichier zip ici présent contient uniquement les sources de MediaSPIP en version standalone.
Pour avoir une installation fonctionnelle, il est nécessaire d’installer manuellement l’ensemble des dépendances logicielles sur le serveur.
Si vous souhaitez utiliser cette archive pour une installation en mode ferme, il vous faudra également procéder à d’autres modifications (...) -
Sélection de projets utilisant MediaSPIP
29 avril 2011, parLes exemples cités ci-dessous sont des éléments représentatifs d’usages spécifiques de MediaSPIP pour certains projets.
Vous pensez avoir un site "remarquable" réalisé avec MediaSPIP ? Faites le nous savoir ici.
Ferme MediaSPIP @ Infini
L’Association Infini développe des activités d’accueil, de point d’accès internet, de formation, de conduite de projets innovants dans le domaine des Technologies de l’Information et de la Communication, et l’hébergement de sites. Elle joue en la matière un rôle unique (...)
Sur d’autres sites (7292)
-
Injecting 360 Metadata into an .mp4 file
17 décembre 2019, par TrueCP5I’m working on a library that injects metadata into a .mp4 file to allow the video to be displayed correctly as a 360 video. The input file is a standard .mp4 file in the equirectangular format. I know what metadata needs to be injected I just do not know how to inject it.
I spent some time looking around for libraries that can do this but could only find ones for extracting metadata not injecting/embedding/writing it. The alternative I found was to use Spatial Media as a command line application to inject the metadata more easily. The problem is I know zero python whatsoever so I’m leaning towards a library/nuget package/ffmpeg script.
Does a good nuget package/library exist that can do this or should I go for the alternative option ?
Edit 1
I have tried just pasting in the metadata into the correct place in the file, just in case it might work, but it didn’t.
Edit 2
This is the metadata injected by Google’s Spatial Media Tool which is what I am trying to achieve :
<?xml version="1.0"?>truetrueSpherical Metadata Toolequirectangular`
Edit 3
I’ve also tried to do it with ffmpeg like so :
ffmpeg -i input.mp4 -movflags use_metadata_tags -metadata Spherical=true -metadata Stitched=true -metadata ProjectionType=equirectangular -metadata StitchingSoftware=StreetviewJourney -codec copy output.mp4
I think the issue with the ffmpeg method is that it does not contain the
rdf:SphericalVideo
part which allows the spherical video tags to be used.Edit 4
When I extract the metadata using ffmpeg it contains the spherical tag in the logs but not when I output it to a ffmetadata file. This was the command I used :
ffmpeg -i injected.mp4 -map_metadata -1 -f ffmetadata data.txt
This is the output of the log :
fps, 60 tbr, 15360 tbn, 120 tbc (default)
Metadata:
handler_name : VideoHandler
Side data:
spherical: equirectangular (0.000000/0.000000/0.000000)Edit 5
I also tried to get the metadata using this command :
ffprobe -v error -select_streams v:0 -show_streams -of default=noprint_wrappers=1 injected.mp4
This was the logs it outputted :
TAG:handler_name=VideoHandler
side_data_type=Spherical Mapping
projection=equirectangular
yaw=0
pitch=0
roll=0I then tried to use this command but it didn’t work :
ffmpeg -i chapmanspeak.mp4 -movflags use_metadata_tags -metadata side_metadata_type="Spherical Mapping" -metadata projection=equirectangular -metadata yaw=0 -metadata pitch=0 -metadata roll=0 -codec copy output.mp4
Edit 6
I tried @VC.One’s method but I must be doing something wrong because the output file is unplayable. Here is my code :
public static void Metadata(string inputFile, string outputFile)
{
byte[] metadata = HexStringToByteArray("3C 3F 78 6D 6C 20 76 65 72 73 69 6F 6E 3D 22 31 2E 30 22 3F 3E 3C 72 64 66 3A 53 70 68 65 72 69 63 61 6C 56 69 64 65 6F 0A 78 6D 6C 6E 73 3A 72 64 66 3D 22 68 74 74 70 3A 2F 2F 77 77 77 2E 77 33 2E 6F 72 67 2F 31 39 39 39 2F 30 32 2F 32 32 2D 72 64 66 2D 73 79 6E 74 61 78 2D 6E 73 23 22 0A 78 6D 6C 6E 73 3A 47 53 70 68 65 72 69 63 61 6C 3D 22 68 74 74 70 3A 2F 2F 6E 73 2E 67 6F 6F 67 6C 65 2E 63 6F 6D 2F 76 69 64 65 6F 73 2F 31 2E 30 2F 73 70 68 65 72 69 63 61 6C 2F 22 3E 3C 47 53 70 68 65 72 69 63 61 6C 3A 53 70 68 65 72 69 63 61 6C 3E 74 72 75 65 3C 2F 47 53 70 68 65 72 69 63 61 6C 3A 53 70 68 65 72 69 63 61 6C 3E 3C 47 53 70 68 65 72 69 63 61 6C 3A 53 74 69 74 63 68 65 64 3E 74 72 75 65 3C 2F 47 53 70 68 65 72 69 63 61 6C 3A 53 74 69 74 63 68 65 64 3E 3C 47 53 70 68 65 72 69 63 61 6C 3A 53 74 69 74 63 68 69 6E 67 53 6F 66 74 77 61 72 65 3E 53 70 68 65 72 69 63 61 6C 20 4D 65 74 61 64 61 74 61 20 54 6F 6F 6C 3C 2F 47 53 70 68 65 72 69 63 61 6C 3A 53 74 69 74 63 68 69 6E 67 53 6F 66 74 77 61 72 65 3E 3C 47 53 70 68 65 72 69 63 61 6C 3A 50 72 6F 6A 65 63 74 69 6F 6E 54 79 70 65 3E 65 71 75 69 72 65 63 74 61 6E 67 75 6C 61 72 3C 2F 47 53 70 68 65 72 69 63 61 6C 3A 50 72 6F 6A 65 63 74 69 6F 6E 54 79 70 65 3E 3C 2F 72 64 66 3A 53 70 68 65 72 69 63 61 6C 56 69 64 65 6F 3E");
byte[] stco = HexStringToByteArray("73 74 63 6F");
byte[] moov = HexStringToByteArray("6D 6F 6F 76");
byte[] trak = HexStringToByteArray("74 72 61 6B");
byte[] file = File.ReadAllBytes(inputFile);
//find trak
int trakPosition = 0;
for (int a = 0; a < file.Length - trak.Length; a++)
{
for (int b = 0; b < trak.Length; b++)
{
if (file[a + b] != trak[b])
break;
if (b == trak.Length - 1)
trakPosition = a;
}
}
if (trakPosition == 0)
throw new FileLoadException();
//add metadata
int trakLength = BitConverter.ToInt32(new ArraySegment<byte>(file, trakPosition - 4, 4).Reverse().ToArray(), 0);
var fileList = file.ToList();
fileList.InsertRange(trakPosition - 4 + trakLength, metadata);
file = fileList.ToArray();
////change length - tried this as well
//byte[] trakBytes = BitConverter.GetBytes(trakLength + metadata.Length).Reverse().ToArray();
//for (int i = 0; i < 4; i++)
// file[trakPosition - 4 + i] = trakBytes[i];
//find moov
int moovPosition = 0;
for (int a = 0; a < file.Length - moov.Length; a++)
{
for (int b = 0; b < moov.Length; b++)
{
if (file[a + b] != moov[b])
break;
if (b == moov.Length - 1)
moovPosition = a;
}
}
if (moovPosition == 0)
throw new FileLoadException();
//change length
int moovLength = BitConverter.ToInt32(new ArraySegment<byte>(file, moovPosition - 4, 4).Reverse().ToArray(), 0);
byte[] moovBytes = BitConverter.GetBytes(moovLength + metadata.Length).Reverse().ToArray();
for (int i = 0; i < 4; i++)
file[moovPosition - 4 + i] = moovBytes[i];
//find stco
int stcoPosition = 0;
for (int a = 0; a < file.Length - stco.Length; a++)
{
for (int b = 0; b < stco.Length; b++)
{
if (file[a + b] != stco[b])
break;
if (b == stco.Length - 1)
stcoPosition = a;
}
}
if (stcoPosition == 0)
throw new FileLoadException();
//modify entries
int stcoEntries = BitConverter.ToInt32(new ArraySegment<byte>(file, stcoPosition + 8, 4).Reverse().ToArray(), 0);
for (int a = stcoPosition + 12; a < stcoPosition + 12 + stcoEntries * 4; a += 4)
{
int entryLength = BitConverter.ToInt32(new ArraySegment<byte>(file, a, 4).Reverse().ToArray(), 0);
byte[] newEntry = BitConverter.GetBytes(entryLength + metadata.Length).Reverse().ToArray();
for (int b = 0; b < 4; b++)
file[a + b] = newEntry[b];
}
File.WriteAllBytes(outputFile, file);
}
private static byte[] HexStringToByteArray(string hex)
{
hex = hex.Replace(" ", "");
return Enumerable.Range(0, hex.Length)
.Where(x => x % 2 == 0)
.Select(x => Convert.ToByte(hex.Substring(x, 2), 16))
.ToArray();
}
</byte></byte></byte></byte>The bytes are reversed because .mp4s seem to be Little Endian. I tried to also update the length of
trak
but that didn’t work either. -
Send AVPacket over Network
2 décembre 2019, par YondonatorI’m generating AVPackets with an encoder with ffmpeg and now I want to send them with UDP to another Computer and show them there.
The problem is I don’t know how to convert the packet to bytes and back. I tried this to copy the package :AVPacket newPacket = avcodec.av_packet_alloc();
ByteBuffer byteBuffer = packet.buf().buffer().asByteBuffer();
int bufferSize = byteBuffer.capacity();
byte bytes[] = new byte[bufferSize];
byteBuffer.get(bytes);
AVBufferRef newBufferRef = avutil.av_buffer_alloc(bufferSize);
newBufferRef.data(new BytePointer(bytes));
newPacket.buf(newBufferRef);
ByteBuffer dataBuffer = packet.data().asByteBuffer();
int dataSize = dataBuffer.capacity();
byte dataBytes[] = new byte[dataSize];
dataBuffer.get(dataBytes);
BytePointer dataPointer = new BytePointer(dataBytes);
newPacket.data(dataPointer);
newPacket.dts(packet.dts());
newPacket.duration(packet.duration());
newPacket.flags(packet.flags());
newPacket.pos(packet.pos());
newPacket.pts(packet.pts());
newPacket.side_data_elems(0);
newPacket.size(packet.size());
newPacket.stream_index(packet.stream_index());
videoPlayer.sendPacket(newPacket);This gives me this Error :
[h264 @ 0000018951be8440] Invalid NAL unit size (3290676 > 77).
[h264 @ 0000018951be8440] Error splitting the input into NAL units.
[h264 @ 0000018951bf6480] Invalid NAL unit size (15305314 > 163).
[h264 @ 0000018951bf6480] Error splitting the input into NAL units.The problem is
newPacket.data()
. When I set it directly :newPacket.data(packet.data())
it works. Alsopacket.data().asByteBuffer().capacity()
returns 1 andpacket.data().capacity()
returns 0.This is my method that creates the decoder :
private void startUnsafe() throws Exception
{
int result;
convertContext = null;
codec = null;
codecContext = null;
AVFrame = null;
RGBAVFrame = null;
frame = new Frame();
codec = avcodec_find_decoder(codecID);
if(codec == null)
{
throw new Exception("Unable to find decoder");
}
codecContext = avcodec_alloc_context3(codec);
if(codecContext == null)
{
releaseUnsafe();
throw new Exception("Unable to alloc codec context!");
}
AVCodecParameters para = avcodec_parameters_alloc();
para.bit_rate(streamBitrate);
para.width(streamWidth);
para.height(streamHeight);
para.codec_id(codecID);
para.codec_type(AVMEDIA_TYPE_VIDEO);
try
{
byte extradataByte[] = Files.readAllBytes(new File("extradata.byte").toPath());
para.extradata(new BytePointer(extradataByte));
para.extradata_size(extradataByte.length);
}
catch (IOException e1)
{
e1.printStackTrace();
throw new Exception("extradata file not available");
}
result = avcodec_parameters_to_context(codecContext, para);
if(result < 0)
{
throw new Exception("Unable to copy parameters to context! [" + result + "]");
}
codecContext.thread_count(0);
result = avcodec_open2(codecContext, codec, new AVDictionary());
if(result < 0)
{
releaseUnsafe();
throw new Exception("Unable to open codec context![" + result + "]");
}
AVFrame = av_frame_alloc();
if(AVFrame == null)
{
releaseUnsafe();
throw new Exception("Unable to alloc AVFrame!");
}
RGBAVFrame = av_frame_alloc();
if(RGBAVFrame == null)
{
releaseUnsafe();
throw new Exception("Unable to alloc AVFrame!");
}
initRGBAVFrame();
TimerTask task = new TimerTask() {
@Override
public void run()
{
timerTask();
}
};
timer = new Timer();
timer.scheduleAtFixedRate(task, 0, (long) (1000/streamFramerateDouble));
window.setVisible(true);
}The file extradata.byte has some bytes that I got from another video, because without them it doesn’t work too.
EDIT :
package org.stratostream.streaming;
import java.nio.ByteBuffer;
import org.bytedeco.javacpp.BytePointer;
import org.bytedeco.javacpp.Pointer;
import org.bytedeco.javacpp.avcodec;
import org.bytedeco.javacpp.avutil;
import org.bytedeco.javacpp.avcodec.AVPacket;
import org.bytedeco.javacpp.avcodec.AVPacketSideData;
public class PacketIO {
public static final int SIDE_DATA_FIELD = 0;
public static final int SIDE_ELEMENTS_FIELD = 4;
public static final int SIDE_TYPE_FIELD = 8;
public static final int DTS_FIELD = 12;
public static final int PTS_FIELD = 20;
public static final int FLAGS_FIELD = 28;
public static final int DATA_OFFSET = 32;
public static byte[] toByte(AVPacket packet) throws Exception
{
int dataSize = packet.size();
ByteBuffer dataBuffer = packet.data().capacity(dataSize).asByteBuffer();
byte dataBytes[] = new byte[dataSize];
dataBuffer.get(dataBytes);
AVPacketSideData sideData = packet.side_data();
int sideSize = sideData.size();
ByteBuffer sideBuffer = sideData.data().capacity(sideSize).asByteBuffer();
byte sideBytes[] = new byte[sideSize];
sideBuffer.get(sideBytes);
int sideOffset = DATA_OFFSET + dataSize;
int resultSize = sideOffset + sideSize;
byte resultBytes[] = new byte[resultSize];
System.arraycopy(dataBytes, 0, resultBytes, DATA_OFFSET, dataSize);
System.arraycopy(sideBytes, 0, resultBytes, sideOffset, sideSize);
resultBytes[SIDE_DATA_FIELD] = (byte) (sideOffset >>> 24);
resultBytes[SIDE_DATA_FIELD+1] = (byte) (sideOffset >>> 16);
resultBytes[SIDE_DATA_FIELD+2] = (byte) (sideOffset >>> 8);
resultBytes[SIDE_DATA_FIELD+3] = (byte) (sideOffset >>> 0);
int sideType = sideData.type();
intToByte(resultBytes, SIDE_TYPE_FIELD, sideType);
int sideElements = packet.side_data_elems();
intToByte(resultBytes, SIDE_ELEMENTS_FIELD, sideElements);
long dts = packet.dts();
longToByte(resultBytes, DTS_FIELD, dts);
long pts = packet.pts();
longToByte(resultBytes, PTS_FIELD, pts);
int flags = packet.flags();
intToByte(resultBytes, FLAGS_FIELD, flags);
return resultBytes;
}
public static AVPacket toPacket(byte bytes[]) throws Exception
{
AVPacket packet = avcodec.av_packet_alloc();
int sideOffset = byteToInt(bytes, SIDE_DATA_FIELD);
int sideElements = byteToInt(bytes, SIDE_ELEMENTS_FIELD);
int sideType = byteToInt(bytes, SIDE_TYPE_FIELD);
int dataSize = sideOffset - DATA_OFFSET;
int sideSize = bytes.length - sideOffset;
long pts = byteToLong(bytes, PTS_FIELD);
long dts = byteToLong(bytes, DTS_FIELD);
int flags = byteToInt(bytes, FLAGS_FIELD);
packet.pts(pts);
packet.dts(dts);
packet.flags(flags);
Pointer newDataPointer = avutil.av_malloc(bytes.length);
BytePointer dataPointer = new BytePointer(newDataPointer);
byte dataBytes[] = new byte[dataSize];
System.arraycopy(bytes, DATA_OFFSET, dataBytes, 0, dataSize);
dataPointer.put(dataBytes);
packet.data(dataPointer);
packet.size(dataSize);
Pointer newSidePointer = avutil.av_malloc(sideSize);
BytePointer sidePointer = new BytePointer(newSidePointer);
byte sideBytes[] = new byte[sideSize];
System.arraycopy(bytes, sideOffset, sideBytes, 0, sideSize);
sidePointer.put(sideBytes);
AVPacketSideData sideData = new AVPacketSideData();
sideData.data(sidePointer);
sideData.type(sideType);
sideData.size(sideSize);
//packet.side_data(sideData);
//packet.side_data_elems(sideElements);
return packet;
}
private static void intToByte(byte[] bytes, int offset, int value)
{
bytes[offset] = (byte) (value >>> 24);
bytes[offset+1] = (byte) (value >>> 16);
bytes[offset+2] = (byte) (value >>> 8);
bytes[offset+3] = (byte) (value >>> 0);
}
private static void longToByte(byte[] bytes, int offset, long value)
{
bytes[offset] = (byte) (value >>> 56);
bytes[offset+1] = (byte) (value >>> 48);
bytes[offset+2] = (byte) (value >>> 40);
bytes[offset+3] = (byte) (value >>> 32);
bytes[offset+4] = (byte) (value >>> 24);
bytes[offset+5] = (byte) (value >>> 16);
bytes[offset+6] = (byte) (value >>> 8);
bytes[offset+7] = (byte) (value >>> 0);
}
private static int byteToInt(byte[] bytes, int offset)
{
return (bytes[offset]<<24)&0xff000000|(bytes[offset+1]<<16)&0x00ff0000|(bytes[offset+2]<<8)&0x0000ff00|(bytes[offset+3]<<0)&0x000000ff;
}
private static long byteToLong(byte[] bytes, int offset)
{
return (bytes[offset]<<56)&0xff00000000000000L|(bytes[offset+1]<<48)&0x00ff000000000000L|(bytes[offset+2]<<40)&0x0000ff0000000000L|(bytes[offset+3]<<32)&0x000000ff00000000L|(bytes[offset+4]<<24)&0x00000000ff000000L|(bytes[offset+5]<<16)&0x0000000000ff0000L|(bytes[offset+6]<<8)&0x000000000000ff00L|(bytes[offset+7]<<0)&0x00000000000000ffL;
}
}Now I have this class that works fine on the same programm, but when I send the bytes over the network I get a bad output and this error is printed to the console :
[h264 @ 00000242442acc40] Missing reference picture, default is 72646
[h264 @ 000002424089de00] Missing reference picture, default is 72646
[h264 @ 000002424089e3c0] mmco: unref short failure
[h264 @ 000002424081a580] reference picture missing during reorder
[h264 @ 000002424081a580] Missing reference picture, default is 72652
[h264 @ 000002424082c400] mmco: unref short failure
[h264 @ 000002424082c400] co located POCs unavailable
[h264 @ 000002424082c9c0] co located POCs unavailable
[h264 @ 00000242442acc40] co located POCs unavailable
[h264 @ 000002424089de00] mmco: unref short failureI think its because I dont set the sidedata field but when I try to set it the encoder crashes with the second packet.
The output looks like this :
Decoder Output -
Shell out to FFMPEG from Windows Service sometimes hangs
17 avril 2013, par Jake StevensonWe have a windows service which runs on multiple machines, waiting for MSMQ messages telling it to convert various files for us. Sometimes the files are video files and we shell out an ffmpeg process to do the conversion and wait for the process to complete or error before moving on. And on some occasions, that ffmpeg process appears to "hang" and we have to RDP to the machine as an admin and manually kill it off using task manager before it can continue to accept new messages. This hung ffmpeg process will stay that way indefinitely, I've waited several days on some occasions. The services all run under a special account.
The conversion process involves multiple steps— First copying the file locally, then running ffmpeg to convert, then running mp4box for "hinting", then another ffmpeg for a thumbnail. When it hangs, it is always on the first ffmpeg portion. Killing the ffmpeg process causes that code to receive an error and allows it to handle things normally from there.
Here is the code for that first FFMPEG process. As you can see, we've tried several things to detect a hung process :
public class FFMPEGEncoder : IEncoder
{
[DllImport("kernel32.dll", SetLastError = true)]
static extern int SetErrorMode(int wMode);
private ILogger _logger = NullLogger.Instance;
public ILogger Logger
{
get { return _logger; }
set { _logger = value; }
}
private static readonly string ffmpeg = System.IO.Path.Combine(ConfigurationManager.AppSettings["FFMPEG_Dir"], "ffmpeg.exe");
private const string ffmpegArgs =
"-r 30000/1001 -b 200k -bt 240k -vcodec libx264 -coder 0 -bf 0 -flags2 -wpred-dct8x8 -level 13 -maxrate 768k -acodec libfaac -ac 2 -ar 48000 -ab 192k -s 480x320 -async 1";
public EncoderResult EncodeTheFile(string originalFile)
{
var newFileName =
VideoFileNameHelper.GetVideoFileName(originalFile);
Logger.Debug("Encoding {0} to {1} with ffmpeg", originalFile, newFileName);
RunEncoding(originalFile, newFileName);
return new EncoderResult { Filename = newFileName };
}
private void RunEncoding(string originalFile, string newFileName)
{
var process = new System.Diagnostics.Process
{
StartInfo =
{
CreateNoWindow = true,
WorkingDirectory = ConfigurationManager.AppSettings["FFMPEG_Dir"],
UseShellExecute = false,
FileName = ffmpeg,
Arguments = "-i \"" + originalFile + "\" " + ffmpegArgs + " \"" + newFileName + "\"",
RedirectStandardOutput = false,
RedirectStandardError = true
}
};
Logger.Debug("Launching ffmpeg with the following arguments:");
Logger.Debug(process.StartInfo.Arguments);
int oldMode = SetErrorMode(3);
var startTime = DateTime.Now;
process.Start();
var output = process.StandardError.ReadToEnd();
Logger.Debug("ffmpeg output:");
Logger.Debug(output);
while(!process.WaitForExit(3000))
{
if (!process.Responding)
{
process.Kill();
SetErrorMode(oldMode);
throw new Exception("Process hung");
}
if (DateTime.Now.Subtract(startTime) > new TimeSpan(0, 0, 30, 0))
{
process.Kill();
SetErrorMode(oldMode);
throw new Exception("Process hung");
}
}
SetErrorMode(oldMode);
var exitCode = process.ExitCode;
if (exitCode != 0)
{
//We got an error from ffmpeg
process.Close();
if (System.IO.File.Exists(newFileName))
{
System.IO.File.Delete(newFileName);
}
Logger.Error("Error converting video {0}", originalFile);
throw new Exception(string.Format("Unable to process the video {0}", originalFile));
}
process.Close();
}
}Despite the errormode setting code AND the code that tries to kill the process after 30 minutes, I still end up with it hung occasionally and have to manually kill the process. What am I doing wrong that would allow my system to more gracefully handle the "hung" ffmpeg processes ?