将视频和音频与 moviepy 结合时音频不同步

时间:2021-04-23 21:44:42

标签: python youtube moviepy pytube

我自己写了一个用于练习的 youtube 下载器,可以下载视频和音频。所以问题是,全高清 <= 格式大多不包含任何音频。所以我的解决方案是单独下载音频,然后将其与moviepy组合在一起。我的问题是,当我观看最终输出时,音频比视频晚了大约 0.5 秒,这看起来很奇怪。代码(它很糟糕,但只是一个练习):

from pytube import YouTube
from moviepy.editor import VideoFileClip
from time import sleep
import os


def convert_to_mp3(filename):#method to convert to mp3 since i havent found a way to download mp3
    clip = VideoFileClip(filename)
    clip.audio.write_audiofile(filename[:-4] + ".mp3")
    clip.close()


def input_link():#get the yt link
    print("Videolink:")

    link = input()

    return link


while True:#check the link until its correct
    try:
        link = input_link()

        video = YouTube(link)
        break
    except Exception:
        print("Fehler im Link!\n")
print("\n1) Video\n2) Audio")

def download_video(itag, name=video.title):#download the video and return the type
    # print(video.streams.filter(file_extension="mp4").all)
    name = video.streams.get_by_itag(itag).download(filename=name)
    if name.__contains__(".webm"):
        return "webm"
    elif name.__contains__(".mp4"):
        return "mp4"
    else:
        print("Unknown format... Name of the file: " + name)
        return "unknown"


def combine_audio(vidname, audname, outname, fps=25):#combine the audio and the video with moviepy
    import moviepy.editor as mpe
    my_clip = mpe.VideoFileClip(vidname)
    audio_background = mpe.AudioFileClip(audname)
    final_clip = my_clip.set_audio(audio_background)
    final_clip.write_videofile(outname)
    print("removing " + vidname)
    os.remove(vidname)
    print("removing " + audname)
    os.remove(audname)


video_audio = input()

def download_video_only(download=True):#function to download the video
    global fps
    formats = str(video.streams.filter().all)
    formatsFormattet = formats[formats.index("[") + 1:formats.index("]")]
    formatsList = []
    while formatsFormattet != "":#prepares the list of the available formats, ill make a method to sort out doubles later
        try:
            formatsList.append(formatsFormattet[formatsFormattet.index(":") + 1:formatsFormattet.index(",") + 1])
        except ValueError:
            formatsList.append(formatsFormattet[formatsFormattet.index(":") + 1:len(formatsFormattet)])
        try:
            formatsFormattet = formatsFormattet[formatsFormattet.index(",") + 1: len(formatsFormattet)]
        except ValueError:
            formatsFormattet = ""
    counter = 1
    itagList = []
    for element in formatsList:
        try:
            element = element[element.index("itag=") + 6:len(element)]
            if element[2] == '"':
                itagList.append(element[0:2])
            else:
                itagList.append(element[0:3])
                # print("\nItag: " + element[0:3])
            element = element[element.index("res=") + 5:len(element)]
            print("\n" + str(counter) + ")\nAuflösung: " + element[0:element.index("\"")])
            element = element[element.index("fps=") + 5:len(element)]
            fps = element[0:element.index("\"")]
            print("Fps: " + element[0:element.index("\"")])
            counter += 1
        except ValueError:
            break
    counter -= 1
    while True:
        print("\nWelches Format hätten sie gerne(1-" + str(counter)+ ")")#print all the formats for the user to select one
        selection = input()
        if int(selection) - 1 < len(formatsList):
            # print(formatsList[int(selection) - 1])
            if download:
                if video.streams.get_by_itag(itagList[int(selection) - 1]).is_progressive:#if the video has audio, just download it
                    download_video(itagList[int(selection) - 1])
                else:#if the video has no audio, download audio and video and combine it after finding out the format
                    download_audio_only(name="audio")
                    type = download_video(itagList[int(selection) - 1], name="video")
                    if(type == "webm"):
                        combine_audio("video.webm", "audio.mp3", video.title + ".mp4", fps)
                    elif type == "mp4":
                        combine_audio("video.mp4", "audio.mp3", video.title + ".mp4", fps)
                    elif type == "unknown":
                        return

            else:
                return itagList[int(selection) - 1]
            break
        print("\nUngültige Eingabe, bitte richtige Eingabe tätigen")


def download_audio_only(name=video.title):#download the audio and make it to mp3
    file = video.streams.filter(only_audio=True).first().download(filename=name)
    sleep(1)
    print(file)
    os.rename("audio.mp4", "audio.mp3")


if int(video_audio) == 1:#get selection for video or audio
    download_video_only()
else:
    download_audio_only()

关于如何解决这个问题的任何想法? 感谢您的帮助

0 个答案:

没有答案