When converting .mov to .flv video plays horizontally - ffmpeg

When I record a video (.mov) through my iPhone it display vertically which is right.
But after converting the .mov to .flv(using ffmpeg) it displays horizontally.
My code:
function convert_flv($vidtime,$infile, $outfile, $w = 0, $h = 0, $extra_infile = '', $extra_outfile = '') {
$parms = '';
if($w == 0 && $h == 0) {
//$parms .= '-sameq ';
} else {
$parms = '-s {$w}x{$h} ';
}
if($vidtime==60) {
$cmd = ffmpeg($infile, $outfile, $parms.' '.$extra_infile, '-t 00:01:00 -ar 22050 -r 15 -f flv '.$extra_outfile);
} else {
$cmd = ffmpeg($infile, $outfile, $parms.' '.$extra_infile, '-t 00:04:00 -ar 22050 -r 15 -f flv '.$extra_outfile);
}
print_r($cmd);
return $cmd;
}

iPhone's store orientation information in .mov metadata that ffmpeg ignores, leading to rotated output. Correctly parsing the metadata is a problem.
If you're recording movies in a consistent orientation you can rotate them by adding -vf "transpose=1" to your ffmpeg command. Docs for transpose.

The orientation is a meta-data field in the video file - the actual file is not recorded in an alternate orientation. You would need to apply a transform in ffmpeg to rotate the video.

Related

ffmpeg downloading parts of Youtube videos but for some of them they have a black screen for a few seconds

So im using ffmpeg to download some youtube videos with specific start and stop times. My code looks like os.system("ffmpeg -i $(youtube-dl --no-check-certificate -f 18 --get-url %s) -ss %s -to %s -c:v copy -c:a copy %s"% (l, y, z, w)) where the variables would all be the name of the file, the url, and the start and stop times. Some of the vidoes come out just fine, others have a black screen and only a portion of the video, and a very few amount have just audio files. My time is formated as x.y where x would be the seconds and y would be the milliseconds. Is this the issue so I need to transform it to 00:00:00.0 format? Any help is appreciated
os.system("ffmpeg -ss %s -i $(youtube-dl --no-check-certificate -f 18 --get-url %s) -t %s -c:v copy -c:a copy %s"% (l, y, z, w))
-ss start the video with 00:00:00.0000 format
-t the duration of scene in seconds
example if you want to extract a scene from second 30, and a duration of 3 seconds
os.system("ffmpeg -ss 00:00:30.0000 -i $(youtube-dl --no-check-certificate -f 18 --get-url %s) -t 3 -c:v copy -c:a copy %s"% (l, y, z, w))
Try this with Python :)
Add '-c:a', 'copy',to ffmpeg command line (part) helps out with the black picture / frames / screen in the video.
def ydl_info():
ydl_opts = {
'format': 'bestvideo[height<=720][tbr>1][filesize>0.05M]',
'outtmpl': '%(id)s.%(ext)s', # Template for output names.
}
with youtube_dl.YoutubeDL(ydl_opts) as ydl:
info = ydl.extract_info(
'https://www.youtube.com/watch?v=HZhWTjnIn78',
download=False # False for just extract the info
)
return info
def ffmpeg_cut():
info = ydl_info()
URL = info['formats'][-1]['url'] # media_url # If there are several media formats then to get media url for the last format:
START = args.start_time
END = '00:00:03.00'
OUTPUT = os.path.join(args.output, args.name+args.format)
print('Output:', OUTPUT)
#ffmpeg -ss 00:00:15.00 -i "OUTPUT-OF-FIRST URL" -t 00:00:10.00 -c copy out.mp4
#cmd = "ffmpeg -ss {} -i {} -t {} -c copy {}".format(START, URL, END, OUTPUT)
subprocess.call([
'ffmpeg',
'-i', URL,
'-ss', START,
'-t', END,
'-c:a', 'copy', OUTPUT, # '-c:v' copies only video and '-c:a' only audio
])
return None

ffmpeg choose exact frame from long film strip

I'm working with ffmpeg to choose the better thumbnail for my video. and the selection would be based on the slider.
as per the requirement multiple thumbnails not needed just a single long film image and with the help of slider select the thumbnail and save it.
i used below command to get the long strip thumbnail.
ffmpeg -loglevel panic -y -i "video.mp4" -frames 1 -q:v 1 -vf "select=not(mod(n\,40)),scale=-1:120,tile=100x1" video_preview.jpg
I followed the instructions from this tutorial
I'm able to get the long film image:
This is working fine, they moving the image in slider which is fine.
My question is how can I select a particular frame from that slider / film strip. How can I calculate the exact time duration from the slider and then execute a command to extract that frame?
In one of my project I implemented the below scenario. In the code where I'm getting Video duration from the ffmgpeg command, if duration is less than 0.5 second than I set a new thumbnail interval for the same. In your case you should set time interval for the thumbnail creation. Hope this will help you.
$dur = 'ffprobe -i '.$video.' -show_entries format=duration -v quiet -of csv="p=0"';
$duration= exec($dur);
if($duration < 0.5) {
$interval = 0.1;
} else {
$interval = 0.5;
}
screenshot size
$size = '320x240';
ffmpeg command
$cmd = "ffmpeg -i $video -deinterlace -an -ss $interval -f mjpeg -t 1 -r 1 -y $image";
exec($cmd);
You can try this:
ffmpeg -vsync 0 -ss duration -t 0.0001 -noaccurate_seek -i filename -ss 00:30 -t 0.0001 -noaccurate_seek -i filename -filter_complex [0:v][1:v] concat=n=2[con];[con]scale=80:60:force_original_aspect_ratio=decrease[sc];[sc]tile=2x1[out] -map [out]:v -frames 1 -f image2 filmStrip.jpg
2 frame

How to Create video from selected images of a folder using FFMPEG?

For the time being I am doing
ProcessStartInfo ffmpeg = new ProcessStartInfo();
ffmpeg.CreateNoWindow = false;
ffmpeg.UseShellExecute = false;
ffmpeg.FileName = "e:\ffmpeg\ffmpeg.exe";
ffmpeg.Arguments = "for file in (D:\\Day\\*.jpg); do ffmpeg -i \"$file\" -vf fps=1/60 -q:v 3 \"D:\\images\\out.mp4\"; done;";
ffmpeg.RedirectStandardOutput = true;
Process x = Process.Start(ffmpeg);
Here I'm getting exception saying system cannot find specified file.
For time being I'm considering all the files in D:\Day\*.jpg but actually I need to query individual files from a list.
Where am I wrong in the above scenario?
We need to create a separate text file with the image names and use that text file to create your video.
inside frameList.txt :
file 'D:\20180205_054616_831.jpg'
file 'D:\20180205_054616_911.jpg'
file 'D:\20180205_054617_31.jpg'
file 'D:\20180205_054617_111.jpg'
and in Arguments of the process use,
"-report -y -r 15/1 -f concat -safe 0 -i frameList.txt -c:v libx264 -s 1920*1080 -b:v 2000k -vf fps=15,format=yuv420p out.mp4"

ffmpeg 1 image with many frames

Is that possible to create thumbnails of video using ffmpeg in this format:
I need to output a single image with vertical shots every 10 seconds.
I know only how to create one image with one frame:
<?php
$ffmpeg = '/usr/local/bin/ffmpeg';
$video = '1.mp4';
$image = '1.png';
$interval = 1;
$size = '300x210';
$cmd = "$ffmpeg -i $video -deinterlace -an -ss $interval -f mjpeg -t 1 -r 1 -y -s $size $image 2>&1";
$return = `$cmd`;
?>
You can do this with one ffmpeg command.
Example
ffmpeg -i alone_in_the_wilderness.mp4 -filter_complex \
"select='isnan(prev_selected_t)+gte(t-prev_selected_t\,10)',yadif,scale=240:-1,tile=1x3" \
-vframes 1 -t 30 -q:v 4 strip.jpg
Example with borders
tile=1x3:margin=10:padding=10
Also see
select, yadif, scale, tile filters documentation
Combine multiple images to form a strip of images ffmpeg
FFmpeg output screenshot gallery
You can get a single image with one frame every 10 seconds with ffmpeg (e.g. 1.png, 2.png, 3.png) in a for loop and then merge the images horizontally using imagemagick:
convert 1.png 2.png 3.png -append vertical.png

ffmpeg transcoding reset the start time of file

I use a segmenter to segment my MPEG 2 Ts file into a series of media segment for HTTP live streaming
and each segment's start time following the previous one
(ex:start time of segments: 00:00,00:10,00:20,00:30,...)
(In Ubuntu)
The Question is:
When I use ffmpeg to transcode one of the media segment (ex 800k bps to 200k bps)
the start time of transcoded media segment will be reset to 0
ex:As I transcode the third segement,
start time of segments changing to : 00:00,00:10,00:00,00:30,...
It cause my player freezing once play the transcoded media segment
Is there any solution to transcode media file with the same start time?
I guess it's the ffmpeg reset the PTS(presentation timestamp) of segment
But I don't know how to fix it...
here is my ffmpeg command (transcode to 250k bps)
============================
ffmpeg -y -i sample-03.ts -f mpegts -acodec libfaac -ar 48000 -ab 64k -vcodec libx264 -b 250k -flags +loop -cmp +chroma \
-partitions +parti4x4+partp8x8+partb8x8 -subq 7 -trellis 0 -refs 0 -coder 0 -me_range 16 -keyint_min 25 \
-sc_threshold 40 -i_qfactor 0.71 -maxrate 250k -bufsize 250k -rc_eq 'blurCplx^(1-qComp)' -qcomp 0.6 \
-qmin 10 -qmax 51 -qdiff 4 -level 30 -aspect 320:240 -g 30 -async 2 sample.ts
============================
Help!
thanks
direct packet time shifting of h264 encoded segments
I ended up linking with ffmpeg libavformat/avcodec libraries to read in, and directly shift the packet time headers. Offset time is specified in seconds
unsigned int tsShift = offsetTime * 90000; // h264 defined sample rate is 90khz
and further below
do {
double segmentTime;
AVPacket packet;
decodeDone = av_read_frame(pInFormatCtx, &packet);
if (decodeDone < 0) {
break;
}
if (av_dup_packet(&packet) < 0) {
cout << "Could not duplicate packet" << endl;
av_free_packet(&packet);
break;
}
if (packet.stream_index == videoIndex && (packet.flags & AV_PKT_FLAG_KEY)) {
segmentTime = (double)pVideoStream->pts.val * pVideoStream->time_base.num / pVideoStream->time_base.den;
}
else if (videoIndex < 0) {
segmentTime = (double)pAudioStream->pts.val * pAudioStream->time_base.num / pAudioStream->time_base.den;
}
else {
segmentTime = prevSegmentTime;
}
// cout << "before packet pts dts " << packet.pts << " " << packet.dts;
packet.pts += tsShift;
packet.dts += tsShift;
// cout << " after packet pts dts " << packet.pts << " " << packet.dts << endl;
ret = av_interleaved_write_frame(pOutFormatCtx, &packet);
if (ret < 0) {
cout << "Warning: Could not write frame of stream" << endl;
}
else if (ret > 0) {
cout << "End of stream requested" << endl;
av_free_packet(&packet);
break;
}
av_free_packet(&packet);
} while (!decodeDone);
mpegts shifter source
shifted streams in a round about way
but the time delta is not precisely what I specify
Here's how
first convert the original ts file into a raw format
ffmpeg -i original.ts original.avi
apply a setpts filter and convert to encoded format
(this will differ depending on frame rate and desired time shift)
ffmpeg -i original.avi -filter:v 'setpts=240+PTS' -sameq -vcodec libx264 shift.mp4
segment the resulting shift.mp4
ffmpeg -i shift.mp4 -qscale 0 -bsf:v h264_mp4toannexb -vcodec copy -an -map 0 -f segment -segment_time 10 -segment_format mpegts -y ./temp-%03d.ts
the last segment file created, temp-001.ts in my case, was time shifted
the problem: this method feels obtuse for merely shifting some ts packet times, and it resulted in a start time of 10.5+ instead of precisely 10 seconds desired for the new ts file
original suggestion did not work as described below
ffmpeg -itoffset prevTime (rest of ts gen args) | ffmpeg -ss prevTime -i _ -t 10 stuff.ts
prevTime is the duration of all previous segments
no good as the second ffmpeg -ss call makes the output mpegts file relative to time 0 (or sometimes 1.4sec - perhaps a bug in the construction of single ts files)
IMO - you have a serialized list of segments and you want to concatenate them.
Thats it as long as the serial order of the segments is preserved thru the concatenation.
Process to run on each segment entry so that it can be concatentated....
getVideoRaw to its own file
getAudioRaw to its own file
When you have splitout to raw all of your segements do this....
concatenate video preserving serialized order so video segments remain correct order in videoConCatOUT.
concatenate the audio as above
then mux the respective concatOUT files into a single container.
This can be scripted and can follow the std. example in the ffmpeg FAQ on Concat
see '3.14.4' section here
Note the 'tail' cmd and the explain about dropping line no. 1 from all except the first segment input to the concat process...
You should transcode before segmenting. When you're transcoding an individual segment, it is creating a new ts stream each time, and the ts time data is not being copied over.
Have a look at the setpts filter. That should give you plenty of control over each piece's PTS.
there is a segmenter muxer https://ffmpeg.org/ffmpeg-formats.html#segment_002c-stream_005fsegment_002c-ssegment which may help you with what you're after...

Resources