I wish to combine a remastered audio track to a video without re-encoding the source video.
I could achieve this with ffmpeg by running this command:
ffmpeg -i original_video.mp4 -i remastered_audio.wav -map 0:v -map 1:a -c:v copy -shortest remastered_video.mp4
The resulting remastered_video.mp4 file will be slightly larger than original_video.mp4 because the video track will be untouched and include the new encoded audio track. I wish to use moviepy to achieve the same, but I can't figure out how to do it without re-encoding the source video.
from moviepy.editor import AudioFileClip, VideoFileClip
original_video = VideoFileClip(<path_to_original_video_file.mp4>)
remastered_audio = AudioFileClip(<path_to_remastered_audio_track.wav>)
remastered_video = original_video.set_audio(remastered_audio)
remastered_video.write_videofile(<path_of_output_remastered_video.mp4>)
Here the output video file will be smaller than the source because the video track was re-encoded.
I then tried to pass my ffmpeg arguments like so:
args=['-map', '0:v', '-map', '1:a', '-c:v', 'copy']
remastered_video.write_videofile(<path_of_output_remastered_video.mp4>,
ffmpeg_params=args,
logger=None)
but that generated the following error:
#[mp4 # 00000190c731d280] Could not find tag for codec rawvideo in stream #0, codec not currently supported in container
#Could not write header for output file #0 (incorrect codec parameters ?): Invalid argument
QUESTION
I know how to use subprocess to directly run ffmpeg, but I would like to avoid this and use moviepy. Is it possible to tell moviepy to copy the source video instead of re-encoding it, similar to the ffmpeg example command I posted above?
Related
I am writting a python code where I am trying to convert a set of images that I take from a FTP into a video using FFMPEG but I cannot. I have tried, instead of reading the folder where the images are, to read a txt file with the name of the images that I want to use, with the format needed in order that FFMPEG could read it propertly, but I get always the same error: Protocol 'ftp' not on whitelist 'tcp'
In the same code, I also try to change the format of one video and change the resolution and size, and this part of code works well.
However, writting as input the same reference of the FTP, the images' code fail and the video's code works.
Besides, I have tried in my terminal as local the same command I write in the code for the images, and in local it works propertly, but not in the code.
Here there is a part of my code:
Video's code (it works):
command = """ffmpeg -i {i} -an -crf {r} {o}""".format(i=src_path,o=path,r=resolution)
An example of this command when I run this is the next (I dont want to write the exact ip and port):
ffmpeg -i ftp://user:user#ip:port/landing_ffmpeg/pruebas/pruebahd.mp4 -an -crf 45 tmp/pruebasalida456.mp4
And next the images' code (it doesnt work):
command = """ffmpeg -loop 1 -framerate {ips} -i {i} -t 10 -pix_fmt yuv420p {o}""".format(i=src_path,o=path,ips=img_per_sec)
An example of this command is the next:
ffmpeg -loop 1 -framerate 2 -i ftp://user:user#ip:port/landing_ffmpeg/pruebas/prueba_imagenes/prueba06.jpg -t 10 -pix_fmt yuv420p tmp/videoimagen.mp4
And the error I get with this code is the next:
[ftp # 0x560eb3e11800] Protocol 'ftp' not on whitelist 'tcp'!
[image2 # 0x560eb3e09380] Could not open file : ftp://user:user#ip:port/landing_ffmpeg/pruebas/prueba_imagenes/prueba06.jpg
I dont get this error when I try to run the command of the video, only for the images. And both commands run propertly when I write in my terminal in local, with local paths.
I would appreciate if someone can help me to solve the problem and fix my code.
Thanks!
The error is saying it all. Try to whitelist the ftp:
ffmpeg -protocol_whitelist ftp -loop 1 -framerate 2 \
-i ftp://user:user#ip:port/landing_ffmpeg/pruebas/prueba_imagenes/prueba06.jpg \
-t 10 -pix_fmt yuv420p tmp/videoimagen.mp4
When reading a video with ffmpeg-python, if the video metadata contains a "rotate" attribute, it seems that by default ffmpeg transposes the incoming bytes according to the rotation value.
I would like to remove the automatic rotation. I tried the following, with no success:
import ffmpeg
process = (
ffmpeg
.input(filename)
.output('pipe:', format='rawvideo', pix_fmt='yuv420p', loglevel=0, vsync='0')
.global_args('-noautorotate')
.run_async(pipe_stdout=True)
)
The code runs without any issue, but the rotation is not ignored, as I would have expected.
According to this:https://gist.github.com/vxhviet/5faf792f9440e0511547d20d17208a76, the noautorotate argument should be passed before input.
I tried the following:
process = (
ffmpeg
.global_args('-noautorotate')
.input(filename)
.output('pipe:', format='rawvideo', pix_fmt='yuv420p', loglevel=0, vsync='0')
.run_async(pipe_stdout=True)
)
also with no success:
AttributeError: module 'ffmpeg' has no attribute 'global_args'
Any suggestion?
EDIT
Passing noautorotate as kwargs does not work either (size of video after reading is 0)
process = (
ffmpeg
.input(self.file, **{'noautorotate':''})
.output('pipe:', format='rawvideo', pix_fmt='yuv420p', loglevel=1, vsync='0')
.run_async(pipe_stdout=True)
)
Replace **{'noautorotate':''} with **{'noautorotate':None}.
Correct syntax:
process = (
ffmpeg
.input(self.file, **{'noautorotate':None})
.output('pipe:', format='rawvideo', pix_fmt='yuv420p', loglevel=1, vsync='0')
.run_async(pipe_stdout=True)
)
When using **{'noautorotate':''}, FFmpeg output an error:
Option noautorotate (automatically insert correct rotate filters) cannot be applied to output url -- you are trying to apply an input option to an output file or vice versa. Move this option before the file it belongs to.
Error parsing options for output file .
Error opening output files: Invalid argument
For testing we may add .global_args('-report'), and look at the log file.
Executing the following command:
process = (
ffmpeg
.input('input.mkv', **{'noautorotate':None})
.output('pipe:', format='rawvideo', pix_fmt='yuv420p', vsync='0')
.global_args('-report')
.run_async()
.wait()
)
The log file shows the built FFmpeg command line - looks correct:
ffmpeg -noautorotate -i input.mkv -f rawvideo -pix_fmt yuv420p -vsync 0 pipe: -report
Executing the following command:
process = (
ffmpeg
.input('input.mkv', **{'noautorotate':''})
.output('pipe:', format='rawvideo', pix_fmt='yuv420p', vsync='0')
.global_args('-report')
.run_async()
.wait()
)
The log file shows the following built FFmpeg command line:
ffmpeg -noautorotate -i input.mkv -f rawvideo -pix_fmt yuv420p -vsync 0 pipe: -report
There is just an extra space before the -i, but for some reason FFmpeg interpret it as a URL (I think it might be a Unicode related issue - the empty strings is interpret as character that is not a space).
I have a below function for merging videos in Python without re-encoding using FFmpeg:
def merge():
"""
This function merges a group of videos into one long video.
It is used for merging parts that are cut from original video into a new one.
The videos are merged using ffmpeg and for the ffmpeg
to use the concat method on them, the video names must be put inside
the vidlist.txt file.
New video is saved to the file named output.mp4.
"""
command = "ffmpeg -hide_banner -loglevel error -f concat -safe 0 -i vidlist.txt -c copy output.mp4"
# merge multiple parts of the video
subprocess.call(command, shell=True)
I store paths to videos to be merged inside a vidlist.txt file which looks like:
file 'out11.mp4'
file 'out21.mp4'
But, I am getting the following error:
vidlist.txt: Invalid data found when processing input
Here is the report file:
ffmpeg started on 2020-07-30 at 20:23:53
Report written to "ffmpeg-20200730-202353.log"
Log level: 48
Command line:
ffmpeg -hide_banner -f concat -safe 0 -i "C:\\Users\\miliv\\videocutter\\utils\\vidlist.txt" -c copy output.mp4 -report
Splitting the commandline.
Reading option '-hide_banner' ... matched as option 'hide_banner' (do not show program banner) with argument '1'.
Reading option '-f' ... matched as option 'f' (force format) with argument 'concat'.
Reading option '-safe' ... matched as AVOption 'safe' with argument '0'.
Reading option '-i' ... matched as input url with argument 'C:\Users\miliv\videocutter\utils\vidlist.txt'.
Reading option '-c' ... matched as option 'c' (codec name) with argument 'copy'.
Reading option 'output.mp4' ... matched as output url.
Reading option '-report' ... matched as option 'report' (generate a report) with argument '1'.
Finished splitting the commandline.
Parsing a group of options: global .
Applying option hide_banner (do not show program banner) with argument 1.
Applying option report (generate a report) with argument 1.
Successfully parsed a group of options.
Parsing a group of options: input url C:\Users\miliv\videocutter\utils\vidlist.txt.
Applying option f (force format) with argument concat.
Successfully parsed a group of options.
Opening an input file: C:\Users\miliv\videocutter\utils\vidlist.txt.
[concat # 000001aaafb8e400] Opening 'C:\Users\miliv\videocutter\utils\vidlist.txt' for reading
[file # 000001aaafb8f500] Setting default whitelist 'file,crypto,data'
[AVIOContext # 000001aaafb97700] Statistics: 0 bytes read, 0 seeks
C:\Users\miliv\videocutter\utils\vidlist.txt: Invalid data found when processing input
The issue was that I was trying to merge video before closing the vidlist.txt file which then didn't allow ffmpeg to open it
I'm trying the 2-pass technique of the FFmpeg in python but couldn't find any python tutorials do this task.
is there is no way instead of using Subprocess? if there's any illustrative example please provide me.
Note:
I have tried the 2-pass in the script like that:
input_fit = {self.video_in:None}
output = {None:"-c:v h264 -b:v 260k -pass 1 -an -f mp4 NUL && ^",
self.video_out:("ffmpeg -i \"%s\" -c:v h264 -b:v 260k -pass 2 " %self.video_in)}
## video_out IS The Name of The output File ##
model = FFmpeg(inputs = input_fit, outputs= output)
print(model.cmd)
It Raises an error of
:: FFRuntimeError: exited with status 1,
but when i take the generated command and run it on the ffmpeg cmd it runs without errors and generates the video perfectly.
so anyone just could tell me what is the problem please?
So I am piping some binary data using RDD.pipe() function to "cat", when I receive the data it is changed so i can't work with it.any I die how to fix it?
I'm using python3
The code and a par of the data is as follows:
line = sc.binaryFiles("files/pipevids")
line.map(lambda x:x[1]).pipe("cat").take(1)
and the original data:
b'RIFF\xeaU\n\x00AVI LIST\x963\x00\x00hdrlavih8\x00\x00\x005\x82\x00\x00\x08L\x01\x00\x00\x00\x00\x00\x10\t\x00\x00<\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x00\x00\x10\x00\x80\x07\x00\x008\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00LIST\x10\x11\x00\x00strlstrh8\x00\x00\x00vidsFMP4\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x1e\x00\x00\x00\x00\x00\x00\x00<\x00\x00\x00\x11x\x00\x00\xff\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x80\x078\x04strfX\x00\x00\x00W\x00\x00\x00\x80\x07\x00\x008\x04\x00\x00\x01\x00\x18\x00FMP4\x00\xec^\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\xb0\x01\x00\x00\x01\xb5\x89\x13\x00\x00\x01\x00\x00\x00\x01 \x00\xc4\x8d\x88\x00\xf5<\x04\x87\x14C\x00\x00\x01\xb2Lavc57.89.100\x00JUNK\x18\x10\x00\x00\x04\x00\x00\x00\x00\x00\x00\x0000dc\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x
The data I receive is:
b\'RIFF\\xeaU\\n\\x00AVI LIST\\x963\\x00\\x00hdrlavih8\\x00\\x00\\x005\\x82\\x00\\x00\\x08L\\x01\\x00\\x00\\x00\\x00\\x00\\x10\\t\\x00\\x00<\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x03\\x00\\x00\\x00\\x00\\x00\\x10\\x00\\x80\\x07\\x00\\x008\\x04\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00LIST\\x10\\x11\\x00\\x00strlstrh8\\x00\\x00\\x00vidsFMP4\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x1e\\x00\\x00\\x00\\x00\\x00\\x00\\x00<\\x00\\x00\\x00\\x11x\\x00\\x00\\xff\\xff\\xff\\xff\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x80\\x078\\x04strfX\\x00\\x00\\x00W\\x00\\x00\\x00\\x80\\x07\\x00\\x008\\x04\\x00\\x00\\x01\\x00\\x18\\x00FMP4\\x00\\xec^\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\xb0\\x01\\x00\\x00\\x01\\xb5\\x89\\x13\\x00\\x00\\x01\\x00\\x00\\x00\\x01 \\x00\\xc4\\x8d\\x88\\x00\\xf5<\\x04\\x87\\x14C\\x00\\x00\\x01\\xb2Lavc57.89.100\\x00JUNK\\x18\\x10\\x00\\x00\\x04\\x00\\x00\\x00\\x00\\x00\\x00\\x0000dc\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\
with an extra '\'
I would like to pipe this to ffmpeg with this command
"ffmpeg -loglevel debug -y -i pipe:0 -f avi pipe:1"
This is because pipe requires a str object.
>>> str(b'RIFF\xeaU\n\x00AVI')
"b'RIFF\\xeaU\\n\\x00AVI'"
>>>
If you want specific representation, you should decode data before passing to pipe.
Unfortunately the result is automatically decoded as UTF-8, so you cannot do much here.