Python get list of streams from video (audio/video) - python

I have a video file and I want to get the list of streams from it. I can see the needed result by for example executing a simple `ffprobe video.mp4:
....
Stream #0:0(eng): Video: h264 (High) (avc1 / 0x31637661) ......
Stream #0:1(eng): Audio: aac (LC) (mp4a / 0x6134706D), ......
....
But I need to use python and code that will work both on Windows and Ubuntu, without executing an external process.
My real goal is to check whether there is ANY audio stream within the video (a simple yes/no would suffice), but I think getting extra information can be helpful for my problem, so I'm asking about the entire streams
EDIT: Clarifying that I need to avoid executing some external process, but looking for some python code/library to do it within the process.

import os
import json
import subprocess
file_path = os.listdir("path to your videos folder")
audio_flag = False
for file in file_path:
ffprobe_cmd = "ffprobe -hide_banner -show_streams -print_format json "+file
process = subprocess.Popen(ffprobe_cmd,stdout=subprocess.PIPE,stderr=subprocess.PIPE, shell=True)
output = json.loads(process.communicate()[0])
for stream in output["streams"]:
if(stream['codec_type'] == 'audio'):
audio_flag = True
break;
if(audio_flag):
print("audio present in the file")
else:
print("audio not present in the file")
# loop through the output streams for more detailed output
for stream in output["streams"]:
for k,v in stream.items():
print(k, ":", v)
Note: Make sure that your videos folder path consist of only valid video files as i didn't include any file validation in the above code snippet. Also, I have tested this code for a video file that contains one video stream and one audio stream.

Related

ffmpeg in python subprocess combine 3 streams

i'd like to combine together three files with ffmpeg through python:
video.webm,
audio1.mp3
audio2.mp3
in a way that takes video stream from video.webm, audio stream from audio1 with delay 10s and audio stream from audio2.mp3 with delay of 30s and i cannot make it work.
this is my current code
ffmpeg=f"{self.ffmpeg_path}ffmpeg" # ffmpeg executable
vid_l=[ffmpeg,'-i',vid_fp] # video input
offset_l1=['-i',audio_fp] # audio input 1
offset_l2=['-i',audio_fp] # audio input 2
map_l=['-filter_complex','adelay=0|1000|2000' , 'amix=inputs=3'] # filter complex thingy
out_l=['-y',out_fp] # overwrite output file
l=vid_l+offset_l1+offset_l2+map_l+out_l # put lists together
self.subprocess_run(l) # run things with subprocess wrapper
thanks in advance

How do I pass an audio file into the microphone?

I know the question does not seems to make sense but let me explain.
So I have a voice changer software that Change the voice in real time. If i open the audacity and choose the micro of that software I can speak and record with the voice changed.
Now what I want is, I have a audio file already recorded and I want to pass that file into that same microphone (to simulate me speaking) and save the output with the voice changed in another file. I made some attemps using pyaudio but no success.
The idea here is to use a tts module in python to read a dataset I have with multiple lines, save the output in a file and then pass that output to the microphone to change the voice and save in another file. That way I can automate a creation of a new dataset with a new speaker to train a new tts. But the problem is I missing the way to pass a file to the microphone to simulate me speaking to it but instead using an audio file already recorded.
Sorry of it was confused. I made my best to explain. Hope someone can help me.
Thank you in advanced!
This is what I have but no success.
import pyaudio
import wave
# Open the audio file
wf = wave.open("my_audio_file.wav", "rb")
# Open the output file
wf_out = wave.open("my_output_file.wav", "wb")
# Set the output file's format and parameters to match the input file
wf_out.setframerate(wf.getframerate())
wf_out.setsampwidth(wf.getsampwidth())
wf_out.setnchannels(wf.getnchannels())
# Open the microphone using pyaudio
p = pyaudio.PyAudio()
# Create a stream to send the audio data to the microphone
stream = p.open(format=p.get_format_from_width(wf.getsampwidth()),
channels=wf.getnchannels(),
rate=wf.getframerate(),
output=True)
# Start streaming the audio data to the microphone
stream.start_stream()
# Send the audio data to the stream and output file
data = wf.readframes(1024)
while data != "":
stream.write(data)
wf_out.writeframes(data)
data = wf.readframes(1024)
# Stop the stream
stream.stop_stream()
# Close the stream, microphone, and output file
stream.close()
p.terminate()
wf_out.close()

How to extract MXF file data?

Is there any way to extract MXF (Material Exchange Format) file data using python?
All I want to do is get data like video duration, actual video stream and if possible the voice in mp3 or any audio format from an MXF file.
You can do those things using ffmpeg-python.
Example of how to extract video duration:
import ffmpeg
filename = 'sample_960x400_ocean_with_audio.mxf'
# Get duration
# Credit: https://github.com/kkroening/ffmpeg-python/issues/545#issuecomment-836792082
video_info = ffmpeg.probe(filename)
duration = float(video_info['format']['duration'])
print(f'Duration: {duration} seconds')
Example of how to convert the audio to MP3:
import ffmpeg
filename = 'sample_960x400_ocean_with_audio.mxf'
# Load file
in_file = ffmpeg.input(filename)
# Get audio track, convert to mp3
in_file.output('file.mp3').run()
Example of how to convert the audio and video to mp4:
import ffmpeg
filename = 'sample_960x400_ocean_with_audio.mxf'
# Load file
in_file = ffmpeg.input(filename)
# Get video, convert to mp4
in_file.output('file.mp4').run()
Note that to use ffmpeg-python, you must install both ffmpeg-python and ffmpeg. See the documentation for more.

No audio when adding Mp3 to VideoFileClip MoviePy

I'm trying to add an mp3 audio file to a video clip that I'm creating out of images with MoviePy. When the script runs it creates the mp4 file and plays successfully, however there's no audio. I'm not really sure why and can't seem to find a ton of documentation around this in general. MoviePy is pretty new to me so any help would be appreciated - thank-you!
def make_video(images):
image_clips = []
for img in images:
if not os.path.exists(img):
raise FileNotFoundError(img)
ic = ImageClip(img).set_duration(3)
image_clips.append(ic)
video = concatenate(image_clips, method="compose")
video.set_audio(AudioFileClip("audio.mp3"))
video.write_videofile("mp4_with_audio.mp4", fps=60, codec="mpeg4")
This worked for me:
clip.write_videofile(out_path,
codec='libx264',
audio_codec='aac',
temp_audiofile='temp-audio.m4a',
remove_temp=True
)
Found it here: https://github.com/Zulko/moviepy/issues/51
Admittedly, this question is old but comes high in search results for the problem. I had the same issue and think the solution can be clarified.
The line:
video.set_audio(AudioFileClip("audio.mp3"))
actually does not change the audio track of the "video" object, but returns a copy of the object with the new AudioFileClip attached to it.
That means that the method:
video.write_videofile("mp4_with_audio.mp4", fps=60, codec="mpeg4")
does not write the final file with the new audio track, since the "video" object remains unchanged.
Changing the script as per the below solved the issue for me.
video_with_new_audio = video.set_audio(AudioFileClip("audio.mp3"))
video_with_new_audio.write_videofile("mp4_with_audio.mp4", fps=60, codec="mpeg4")
See also the docs
Check the video mp4_with_audio.mp4 with VLC media player, i also have same issue with quick player.
I run into this problem too. I found a solution, try
video = video.set_audio(AudioFileClip("audio.mp3"))
I was doing something similar and found that moviepy 1.0.1 did not call ffmpeg with the right arguments to combine the video and audio for mp4 video. I solved this through a workaround using ffmpeg directly. It uses the temp audio file and video file from moviepy to create a final file. This is a similar question: Output video has no sound
Since you are working with mp3, you may need to have ffmpeg convert to aac, so this code does that.
This link helped me with ffmpeg:https://superuser.com/questions/277642/how-to-merge-audio-and-video-file-in-ffmpeg
video_with_new_audio = video.set_audio(AudioFileClip("audio.mp3"))
video_with_new_audio.write_videofile("temp_moviepy.mp4", temp_audiofile="tempaudio.m4a",codec="libx264",remove_temp=False,audio_codec='aac')
import subprocess as sp
command = ['ffmpeg',
'-y', #approve output file overwite
'-i', "temp_moviepy.mp4",
'-i', "tempaudio.m4a",
'-c:v', 'copy',
'-c:a', 'aac', #to convert mp3 to aac
'-shortest',
"mp4_with_audio.mp4" ]
with open(ffmpeg_log, 'w') as f:
process = sp.Popen(command, stderr=f)
Use this:
video.write_videofile("output.mp4", fps=30, audio_codec="aac", audio_bitrate="192k")

Python extract wav from video file

Related:
How to extract audio from a video file using python?
Extract audio from video as wav
How to rip the audio from a video?
My question is how could I extract wav audio track from video file, say video.avi?
I read many articles and everywhere people suggest to use (from Python) ffmpeg as a subprocess (because there are no reliable python bindings to ffmpeg - the only hope was PyFFmpeg but i found it is unmaintaned now). I don't know if it is right solution and i am looking for good one.
I looked to gstreamer and found it nice but unable to satisfy my needs -- the only way I found to accomplish this from command line looks like
gst-launch-0.10 playbin2 uri=file://`pwd`/ex.mp4 audio-sink='identity single-segment=true ! audioconvert ! audio/x-raw-int, endianness=(int)1234, signed=(boolean)true, width=(int)16, depth=(int)16, rate=(int)16000, channels=(int)1 ! wavenc ! filesink location=foo.wav’
But it is not efficient because i need to wait ages while playing video and simultaneously writing to wav file.
ffmpeg is much better:
avconv -i foo.mp4 -ab 160k -ac 1 -ar 16000 -vn ffaudio.wav
But i am unable to launch it from python (not as a command line subprocess). Could you please point me out pros and cons of launching ffmpeg from python as a command line utility ? (I mean using python multiprocessing module or something similar).
And second question.
What is simple way to cut long wav file into pieces so that i don't break any words ? i mean pieces of 10-20 sec length with start and end during the pause in sentences/words ?
i know how to break them on arbitrary pieces:
import wave
win= wave.open('ffaudio.wav', 'rb')
wout= wave.open('ffsegment.wav', 'wb')
t0, t1= 2418, 2421 # cut audio between 2413, 2422 seconds
s0, s1= int(t0*win.getframerate()), int(t1*win.getframerate())
win.readframes(s0) # discard
frames= win.readframes(s1-s0)
wout.setparams(win.getparams())
wout.writeframes(frames)
win.close()
wout.close()
It is a very easy Task using ffmpeg with python subprocess and there is a reason why people are pointing to this solution as a good solution.
This is the basic command extracting audio from a given video File:
ffmpeg -i test.mp4 -ab 160k -ac 2 -ar 44100 -vn audio.wav
The Python Code is just wrapping this command:
import subprocess
command = "ffmpeg -i C:/test.mp4 -ab 160k -ac 2 -ar 44100 -vn audio.wav"
subprocess.call(command, shell=True)
You have to make sure that ffmpeg is a known task, so in your system environment variables, under path, the path to ffmpeg.exe should be listed, or you can just use the full path to the exe in your python code.
this could be better and easier to use than ffmpeg, it's called python-video converter, and can be used to extract the audio from video, https://github.com/senko/python-video-converter , it could be used in conjunction with mpg123, as follows
from converter import Converter
import os
c = Converter()
clip = 'clip.avi'
conv = c.convert(clip, 'audio.mp3', {'format':'mp3','audio':{'codec': 'mp3','bitrate':'22050','channels':1}})
for timecode in conv:
pass
os.system("mpg123 -w audio.wav audio.mp3")
the converter module extracts the audio from the video and saves it as an mp3 file, while mpg123 converts the mp3 file to mp4,
a different solution is as follows:
using moviepy module in python https://github.com/Zulko/moviepy
import moviepy.editor as mp
clip = mp.VideoFileClip("video.avi").subclip(0,20)
clip.audio.write_audiofile("theaudio.mp3")
the numbers within the subclip function specify start and end of audio, in seconds. you can then use mpg123 to change the audio to any other format
Audio clips can be created from an audio file or from the soundtrack of a video file
from moviepy.editor import *
audioclip = AudioFileClip("some_audiofile.mp3")
audioclip = AudioFileClip("some_video.avi")
https://zulko.github.io/moviepy/getting_started/audioclips.html
or example extract mp3 from
import os
VIDEOS_PATH = '/Users/****/videos'
VIDEOS_EXTENSION = '.webm' # for example
AUDIO_EXT = 'wav'
EXTRACT_VIDEO_COMMAND = ('ffmpeg -i "{from_video_path}" '
'-f {audio_ext} -ab 192000 '
'-vn "{to_audio_path}"')
os.chdir(VIDEOS_PATH)
files = os.listdir(VIDEOS_PATH)
for f in files:
if not f.endswith(VIDEOS_EXTENSION):
continue
audio_file_name = '{}.{}'.format(f, AUDIO_EXT)
command = EXTRACT_VIDEO_COMMAND.format(
from_video_path=f, audio_ext=AUDIO_EXT, to_audio_path=audio_file_name,
)
os.system(command)

Categories

Resources