I have a video converter which is converting audio and video files. Everything works but if I close my terminal from my server the audio file convert doesnt work anymore. I use PyTube for converting and moviepy for converting the mp4 from pytube into mp3. (I think the problem has something to do with moviepy bc. before I didnt have it.)
This is my code for converting audio:
if format == "3":
yt = YouTube(videolink)
downloads = MEDIA_ROOT + "/videos/"
ys = yt.streams.filter(file_extension='mp4').first().download(downloads)
base, ext = os.path.splitext(ys)
basename = os.path.basename(base + uuid + '.mp3')
videoclip = VideoFileClip(ys)
audioclip = videoclip.audio
audioclip.write_audiofile(base + uuid + ".mp3")
audioclip.close()
videoclip.close()
maybe something with the os code is wrong.
But I cant figure out why it works if I leave the console open.
Im thankful for every help I get.
So I found the solution, for everyone who faces the same problem. You have to disable the console output in moviepy. You can do the with the logger parameter in the "write" function. Then the error should disappear.
Related
I want to make a python script to create a video with moviepy but I have some problems with windows. I tried installing ImageMagick but can not find a convert.exe I do not know why it is. But I am already stuck.
my code:
import moviepy.editor as mp
import os
print("Start")
def create_vertical_video(image_file, music_file, quote):
# Open image and resize to 9:16 aspect ratio (vertical video)
if not os.path.isfile(image_file):
raise ValueError(f"{image_file} is not a valid file path")
image = mp.ImageClip(image_file).resize(height=1080)
# Open music file and set to fit the duration of the image
if not os.path.isfile(music_file):
raise ValueError(f"{music_file} is not a valid file path")
music = mp.AudioFileClip(music_file)
music = music.set_duration(image.duration)
# Split quote into multiple lines if necessary
MAX_CHARS_PER_LINE = 25
lines = []
current_line = ""
for word in quote.split():
if len(current_line) + len(word) <= MAX_CHARS_PER_LINE:
current_line += word + " "
else:
lines.append(current_line.strip())
current_line = word + " "
lines.append(current_line.strip())
# Create text clip for each line
text_clips = [mp.TextClip(line, fontsize=24, color='white', bg_color='black')
.set_pos('center').set_duration(image.duration)
for line in lines]
# Overlay text clips on image
text_overlay = mp.concatenate_videoclips(text_clips, method='compose')
final_clip = mp.CompositeVideoClip([image, text_overlay])
# Add music to final clip
final_clip = final_clip.set_audio(music)
# Save video
final_clip.write_videofile("vertical_video.mp4", fps=24)
create_vertical_video("nature.jpg","music.mp3","Don't be pushed around by the fears in your mind. Be led by the dreams in your heart.")
my error:
[WinError 2] The system cannot find the file specified.
.This error can be due to the fact that ImageMagick is not installed on your computer, or (for Windows users) that you didn't specify the path to the ImageMagick binary in file conf.py, or that the path you specified is incorrect`
In ImageMagick v7, the convert.exe program is replaced by magick.exe.
So if your Python script is looking for convert.exe, you must click "Install legacy commands" when installing ImageMagick.
I am trying to combine a .mp4 file with a .wav file. I am rendering my mp4 with cv2 videowriter, and I don't think it has anyway of incorporating audio with it. I have tried moviepy.editor, and ffmpeg. moviepy.editor kept messing up the video file and ffmpeg repeatedly kept giving me an error that it couldn't edit existing files in-place. Combining .mp4 with another audio file type is also fine, but if so it would be nice to also answer how to convert midi files to the file type you answered with. Thanks for the help!
moviepy.editor workflow:
video = mpe.VideoFileClip(mp4_path)
os.system(f"timidity {midi_path} -Ow -o {wav_path)}") # Convert .mid to .wav
video = video.set_audio(mpe.AudioFileClip(wav_path))
video.write_videofile(mp4_path, fps=fps)
ffmpeg workflow:
video = ffmpeg.input(mp4_path)
os.system(f"timidity {midi_path} -Ow -o {wav_path)}") # Convert .mid to .wav
audio = ffmpeg.input(wav_path)
video = ffmpeg.output(video, audio, path, vcodec='copy', acodec='aac', strict='experimental')
ffmpeg.run(video)
I tested both modules and for moviepy I get correct output video with audio even if I use the same name as output. So I don't know what can mess with output.
For ffmpeg I had to use different name for output file to resolve problem with couldn't edit existing files in-place
I had to also use object.video and object.audio to replace audio in output file.
video = ffmpeg.input(video_path).video # get only video channel
audio = ffmpeg.input(audio_path).audio # get only audio channel
My testing code
def test_moviepy(video_path, audio_path, output_path='output-moviepy.mp4', fps=24):
import moviepy.editor as mpe
print('--- moviepy ---')
video = mpe.VideoFileClip(video_path)
video = video.set_audio(mpe.AudioFileClip(audio_path))
video.write_videofile(output_path, fps=fps)
def test_ffmpeg(video_path, audio_path, output_path='output-ffmpeg.mp4', fps=24):
import ffmpeg
print('--- ffmpeg ---')
video = ffmpeg.input(video_path).video # get only video channel
audio = ffmpeg.input(audio_path).audio # get only audio channel
output = ffmpeg.output(video, audio, output_path, vcodec='copy', acodec='aac', strict='experimental')
ffmpeg.run(output)
# --- main ---
video_path = 'movie.mp4'
audio_path = 'sound.wav'
output_path = 'output.mp4'
test_moviepy(video_path, audio_path)#, output_path)
test_ffmpeg(video_path, audio_path)#, output_path)
EDIT:
After installing python module graphviz and program graphviz I could run
ffmpeg.view(output, filename='output-ffmpeg.png')
to get image
I found that this command using eyed3 works fine on my mp3 file writing the images found to the directory DIR
eyeD3 --write-images=DIR file.mp3
But I would like to use this in a python program could someone give me an example
on how to do that.
This snippet works fine
audiofile = eyed3.load("file.mp3")
print(audiofile.tag.album)
print(audiofile.tag.artist)
print(audiofile.tag.title)
print(audiofile.tag.track_num)
This oughta do it.
I've added the image type as well, as there can be multiple images in a single MP3 file, and you didn't specify which one you needed. For most files this would be the album cover.
import eyed3
audio_file = eyed3.load("test.mp3")
album_name = audio_file.tag.album
artist_name = audio_file.tag.artist
for image in audio_file.tag.images:
image_file = open("{0} - {1}({2}).jpg".format(artist_name, album_name, image.picture_type), "wb")
print("Writing image file: {0} - {1}({2}).jpg".format(artist_name, album_name, image.picture_type))
image_file.write(image.image_data)
image_file.close()
I'm trying to output SVG from AWS Lambda using plotly's plot() method. This works in a local environment but seems to fail in Lambda.
The block of code:
downloadRootFolder = "/tmp/" # Lambda's write directory is /tmp. Other directories will deny access
aFilename = "py_chart_" + uuid.uuid1().hex
plotly.offline.plot(chart,
output_type = "file",
filename = downloadRootFolder + aFilename + ".html", # /tmp/py_chart_UUID.html
image_filename = downloadRootFolder + aFilename, # /tmp/py_chart_UUID
image = "svg", image_width = w, # defined earlier
image_height = h)
myFilename = aFilename + ".svg"
svgText = "<svg>could not find the svg file!</svg>"
maxAttempts = 20
millisecsToWait = 250
print(os.listdir("/tmp/")) # output: ['py_chart_380ac7b4fcf411e9b6c0d273169078fd.html'] (no .svg file)
for c in range(0,maxAttempts):
if os.path.exists(downloadRootFolder + myFilename):
f = open(downloadRootFolder + myFilename,"r")
svgText = f.read()
f.close()
else:
time.sleep(millisecsToWait/1000)
print("look for saved svg file attempt # " + str(c))
return(svgText) # returns "could not find the svg file!"
My understanding of the above code, which I did not write, is that plotly generates SVG by first creating an html with executable JS, which then downloads the html as SVG. We try to open the html file to download SVG, but have to wait and retry several times in case it is taking time. (If you know a better way to do it, please let me know.)
On the print(os.listdir) line, you'll notice the html exists, but either A) The SVG is not being generated, or B) if it is generated, it is written by plotly to some weird directory.
Questions:
1) How do I control the directory plotly.offline.plot() writes SVG to?
2) Where is it attempting to write to on CentOS by default? It's possible it is trying and failing to write there due to Lambda permissions.
3) Is there a "downloads" folder on Lambda outside of /tmp/ that I could check?
4) Is there some other reason Lambda may be failing to export the SVG - for example, unable to open HTML files or unable to loaded embedded JS.
5) Where could I look to further debug this problem?
Appreciate any insight you may have here.
Have you tried plotly.io.write_image? Or something like fig.write_image("images/fig1.svg")
The Plotly docs describe Static Image Export here: https://plot.ly/python/v3/offline/
Basically, convert a figure into image bytes then write to a file.
import plotly.io as pio
static_image_bytes = pio.to_image(fig, format='png')
pio.write_image(fig, file='plotly_static_image.png', format='png')
I have a small program I created to download image files form a FlashAir webdav enabled SD Card. This works fine with Powershell but trying a Python implementation.
I have it working where easywebdav can download the file but the resulting size is 22Kb which is wrong and windows does not recognize them as a valid file.
I have applied a basestring fix to the client.py for handling Python 3.x instead of 2.x found here How to overcome Python 3.4 NameError: name 'basestring' is not defined.
I'm on Python 3.5.1.
import easywebdav
urlFlashAir = 'http://flashair'
imgLocation = '/DCIM/101MSDCF'
destLocation = 'c:\\test3\\'
remoteDirName = ''
webDavConnection = easywebdav.connect('flashair', '', '')
lsOutput = webDavConnection.ls(imgLocation)
for i in lsOutput:
if i.size == 0:
remoteDirName = i.name
if i.size > 0:
filename = (i.name).replace(remoteDirName,'')
print(i.name)
print(remoteDirName)
print(filename)
webDavConnection.download(imgLocation, destLocation + filename)
I inspected the 22KB article with notepad++ and found that it was a web page for the flashair card. Upon investigation of the code and documentation I found I was not referencing the remote filename just the location. Once I fixed the code to append a forward slash and a filename. Now properly downloads the file.