Hintergrundbild für Video mit MeGUI/AVISynth erstellen

Diese Seite verwendet Cookies. Durch die Nutzung unserer Seite erklären Sie sich damit einverstanden, dass wir Cookies setzen. Weitere Informationen

  • Hintergrundbild für Video mit MeGUI/AVISynth erstellen

    Anzeige
    Hallo,

    zurzeit haben wir einen Pokémon Hack am laufen. Das Video das wir aus dem VBA aufnehmen hat das Seitenverhältnis 3:2. Wenn ich das auf eine Höhe von 1080p hochskaliere bleibt immer ein schwarzer Rand, den ich nutzen möchte um Informationen über derzeitiges Team und Aufenthaltsort auf der Karte zu zeigen.
    Siehe Bsp. hier:


    Derzeit habe ich per Gimp ein 1920x1080p Bild, das in dem Bereich leer ist, an die das Video gesetzt wird und in dem Streifen die Pokemon. Das heißt für jede Änderung im Team oder im Ort habe ich ein eigenes Bild. In MeGUI/AVISynth suche ich mir die Stellen an denen sich etwas ändert und lade dann die Bilder per ImageSource in der gewünschten Länge rein, papp sie aneinander und lege dann das Gameplay-Video per Overlay vor das Backgroundvideo.

    Skript hier:
    Spoiler anzeigen

    Quellcode

    1. #Filter Laden
    2. LoadPlugin("G:\Videos\MeGUI_2418_x86\tools\filter\vfrtocfr.dll")
    3. LoadPlugin("G:\Videos\MeGUI_2418_x86\tools\ffms\ffms2.dll")
    4. #Video Laden
    5. video = "rohcfr.mp4"
    6. audio = "sound.wav"
    7. #Laden der Rohdaten
    8. __film = LanczosResize(FFVideoSource(video, threads=1).Crop(76,50,-76,-50),1620,1080)
    9. __audio = WAVSource(audio).SSRC(44100)
    10. #Anfangs- & Endframe, Schnitt
    11. start = 128
    12. end = __film.framecount
    13. #Hintergrund basteln
    14. __bg = ImageSource("VideoBGs\videobg1.png",start=start,end=6870,fps=30)
    15. __bg = __bg ++ ImageSource("VideoBGs\videobg2.png",start=6871,end=7650,fps=30)
    16. __bg = __bg ++ ImageSource("VideoBGs\videobg3.png",start=7651,end=8250,fps=30)
    17. __bg = __bg ++ ImageSource("VideoBGs\videobg4.png",start=8251,end=23784,fps=30)
    18. __bg = __bg ++ ImageSource("VideoBGs\videobg3.png",start=23785,end=26370,fps=30)
    19. __bg = __bg ++ ImageSource("VideoBGs\videobg5.png",start=26371,end=26550,fps=30)
    20. __bg = __bg ++ ImageSource("VideoBGs\videobg6.png",start=26551,end=28950,fps=30)
    21. __bg = __bg ++ ImageSource("VideoBGs\videobg7.png",start=28951,end=28980,fps=30)
    22. __bg = __bg ++ ImageSource("VideoBGs\videobg8.png",start=28981,end=end,fps=30)
    23. __film = AudioDub(__film, __audio)
    24. __film =__film.trim(start, end)
    25. __film = AudioDub(Overlay(__bg,__film,0,0), __film).ConvertToYV12()
    Alles anzeigen


    Wie man sieht, kann das für Parts in denen viel passiert ziemlich eklig werden. Deshalb meine Frage: Gibt es einen eleganteren Weg diesen Hintergrund einzufügen? Auserdem muss ich nach dem Overlay immer noch einmal einen AudioDub ausführen, das das Overlay ja den Sound des hinteren Videos verwendet. Kann das irgendwie umgangen werden?

    Danke schon Mal, und leckere Grütze,
    Sephron
  • Als erstes... machste die Seitenbilder mal nicht so groß. Immer entsprechend Der Größe die noch fehlt.

    16:9 ist deine Zielauflösung mit 1080p
    Der GBA hat eigentlich ein Display von 240×160. Sprich deine 3:2 Auflösung

    Sprich du rechnest dir erst einmal aus damit wie groß deine Bilder werden müssen von der Breite, damit sie die restliche Seite ausfüllen.

    Also:
    (1080 / 160) * 240 = 1620

    Also hat dein Spiel 1620x1080 auf 1080p. Du kannst ruhig sehr korrekt bei dem Spiel da skalieren.

    Jetzt willst du aber eine Zielauflösung von 16:9 haben. Sprich 1920x1080 ist 16:9

    Also:
    1920 - 1620 = 300

    Also muss dein Seitenrahmen nur 300 x 1080 groß werden. Und keine 1920x1080. Mach nicht mehr, was man später eh nicht sieht ^^


    Dann brauchst du kein VFRtoCFR Plugin, da du, wenn du mit dem richtigen Programm aufnimmst, CFR aufnimmst. Und das solltest du auch tun. Sprich: Lass die Finger weg von Shadowplay und sonstige Aufnahmeprogrammen wo du mit der Mediainfo eine VFR bekommst. Ich erschlag nämlich gerne Leute die damit aufnehmen und nicht wissen warum sie es so aufnehmen und dann noch sich fragen warum da was Asynchron wird.

    Auch habe ich immer Optische Augenschmerzen wenn ich bei LPs MP4 in einem Skript sehen muss.

    Dann seh ich Audio was du mit SSRC zwars in 44100Hz bringst... es aber somit in 32 Bit, statt 16Bit ausgibst.

    Alles im Allem.... sehr mieserabel so wie es jetzt ist. Und das schon ohne auf diesen ImageSource sich bezogen zu haben.

    Ich gebe dir daher den Tipp: GBA Spiele bei dem VBA Emulator kannst du Lossless aufnehmen lassen. Entweder Kostenlos mit MSI Afterburner oder Virtual Dub
    Oder aber auch mit Fraps, DXTory sofern du dann Die Grafikengine geändert hast auf Direct3D bzw. OpenGL

    Ist also machbar und gibt dir gewiss auch mehr Qualität so und vor allem gibt dir die Aufnahme mit diesen Programmen gewiss eine CFR und keine VFR.

    Und AVIs (sofern da kein h264 Stream enthalten ist) lassen sich viel schneller und besser encoden via AVISource dann.


    Jetzt zum eigentlichen Problem wieder im Skript... wie die Bilder intelligenter laden?

    Was sich jedesmal ändert an den Bildern ist die Länge und das Bild selbst.

    So würde ich das gerne sehen wollen:
    Bei Verlustfreien Material

    Quellcode

    1. video = "Lossless.avi"
    2. audio = "Lossless.wav"
    3. #Quellen laden und duben
    4. video = AudioDub(AVISource(video, false), WAVSource(sound)).AssumeFPS(30, 1)
    5. #Video Croppen
    6. #Video immer vor dem Resize croppen
    7. video = video.Crop(76,50,-76,-50)
    8. #Audio in 44100Hz, 16Bit Stereo wandeln
    9. video = video.SSRC(44100, false).StereoChannel().ConvertAudioTo16bit()
    10. #Auf eine 3:2 1080p Auflösung skalieren
    11. video = video.Spline16Resize((1080 / 2) * 3, 1080)
    12. #Cut
    13. start = 128
    14. video = video.trim(start, video.framecount)
    15. #Bilder laden und positionieren. Die Bilder müssen eine Höhe der Videoauflösung haben.
    16. #Sprich 1080p
    17. # Youtube hat 16:9 mit 1920x1080
    18. # (1080 / 2) * 3 = 1620 -> Video
    19. # 1920 - 1620 = 300 -> Bilder
    20. # Video: 1620x1080
    21. # Bilder: 300x1080
    22. Bild = Bild("VideoBGs\videobg1.png",start, 6870)
    23. Bild = Bild ++ Bild("VideoBGs\videobg2.png", Bild.framecount, 7650)
    24. Bild = Bild ++ Bild("VideoBGs\videobg3.png", Bild.framecount, 8250)
    25. Bild = Bild ++ Bild("VideoBGs\videobg4.png", Bild.framecount, 23784)
    26. Bild = Bild ++ Bild("VideoBGs\videobg3.png", Bild.framecount, 26370)
    27. Bild = Bild ++ Bild("VideoBGs\videobg5.png", Bild.framecount, 26550)
    28. Bild = Bild ++ Bild("VideoBGs\videobg6.png", Bild.framecount, 28950)
    29. Bild = Bild ++ Bild("VideoBGs\videobg7.png", Bild.framecount, 28980)
    30. Bild = Bild ++ Bild("VideoBGs\videobg8.png", Bild.framecount, video.framecount)
    31. #Clips Horizontal anordnen. Daraus wird aus 1620 + 300 = 1920.
    32. #Zusammen mit der Höhe wird dadurch 1920x1080
    33. StackHorizontal(Video, Bild)
    34. #Funktion für die Bildladesequenz
    35. Function Bild (string bild, int start, int end) {
    36. return ImageReader(bild, start, end, 30).ConvertToYV12()
    37. }
    38. #Funktion um Audio in Stereo zu wandeln auf Basis der ersten beiden Channels
    39. Function StereoChannel(clip audio) {
    40. Try { return audio.GetChannel(1,2) }
    41. Catch (Error_2) { Return audio.GetChannel(1,1) }
    42. }
    Alles anzeigen



    Und das hier müsste mit deiner jetzigen Aufnahme funktionieren:
    Bei deiner jetzigen Verlustquelle

    Quellcode

    1. LoadPlugin("G:\Videos\MeGUI_2418_x86\tools\ffms\ffms2.dll")
    2. video = "rohcfr.mp4"
    3. audio = "sound.wav"
    4. #Quellen laden und duben
    5. video = AudioDub(FFVideoSource(video, threads=1), WAVSource(sound)).AssumeFPS(30, 1)
    6. #Video Croppen
    7. #Video immer vor dem Resize croppen
    8. video = video.Crop(76,50,-76,-50)
    9. #Audio in 44100Hz, 16Bit Stereo wandeln
    10. video = video.SSRC(44100, false).StereoChannel().ConvertAudioTo16bit()
    11. #Auf eine 3:2 1080p Auflösung skalieren
    12. video = video.Spline16Resize((1080 / 2) * 3, 1080)
    13. #Cut
    14. start = 128
    15. video = video.trim(start, video.framecount)
    16. #Bilder laden und positionieren. Die Bilder müssen eine Höhe der Videoauflösung haben.
    17. #Sprich 1080p
    18. # Youtube hat 16:9 mit 1920x1080
    19. # (1080 / 2) * 3 = 1620 -> Video
    20. # 1920 - 1620 = 300 -> Bilder
    21. # Video: 1620x1080
    22. # Bilder: 300x1080
    23. Bild = Bild("VideoBGs\videobg1.png",start, 6870)
    24. Bild = Bild ++ Bild("VideoBGs\videobg2.png", Bild.framecount, 7650)
    25. Bild = Bild ++ Bild("VideoBGs\videobg3.png", Bild.framecount, 8250)
    26. Bild = Bild ++ Bild("VideoBGs\videobg4.png", Bild.framecount, 23784)
    27. Bild = Bild ++ Bild("VideoBGs\videobg3.png", Bild.framecount, 26370)
    28. Bild = Bild ++ Bild("VideoBGs\videobg5.png", Bild.framecount, 26550)
    29. Bild = Bild ++ Bild("VideoBGs\videobg6.png", Bild.framecount, 28950)
    30. Bild = Bild ++ Bild("VideoBGs\videobg7.png", Bild.framecount, 28980)
    31. Bild = Bild ++ Bild("VideoBGs\videobg8.png", Bild.framecount, video.framecount)
    32. #Clips Horizontal anordnen. Daraus wird aus 1620 + 300 = 1920.
    33. #Zusammen mit der Höhe wird dadurch 1920x1080
    34. StackHorizontal(Video, Bild)
    35. #Funktion für die Bildladesequenz
    36. Function Bild (string bild, int start, int end) {
    37. ImageReader(bild, start, end, 30).ConvertToYV12()
    38. return last
    39. }
    40. #Funktion um Audio in Stereo zu wandeln auf Basis der ersten beiden Channels
    41. Function StereoChannel(clip audio) {
    42. Try { return audio.GetChannel(1,2) }
    43. Catch (Error_2) { Return audio.GetChannel(1,1) }
    44. }
    Alles anzeigen


    Wie du siehst wird nur einmal gedubt
    Auch das mit den Bildern ist eleganter gelöst, indem man jetzt nur noch das Bild angeben muss + Endframe bis wann es angezeigt werden soll. Dann folgt das nächste. Sprich den Startwert braucht man nicht mehr angeben, da er mit einer Variable gefüttert wird, die das automatisch macht, da wir ja immer den Clip Bild immer weiter aufbauen.

    Mit StackHorizontal wird nur noch die beiden zusammengesetzt und fertig.

    Diese beiden Skripte sind jetzt auf YV12 ausgelegt. Bedeutet... deine Aufnahmen müssten in YV12 gestaltet werden.
    Deine MP4 wird gewiss YV12 haben.
  • Danke für die Antwort.

    Wir nehmen tatsächlich mit MSIAfterburner auf, und das war gerade ein ziemlich bescheuertes bespiel was die Rohdaten angeht, da wir bei der Aufnahme aus dem VBA rausgetabbt haben, wodurch msi für ca. 2 minuten keine neuen frames, jedoch sound aufgenommen hat, wodurch wir ein ziemlich dämliches Video hatten, bei dem für 2 Minuten eine Framerate von 0 war. Das habe ich (sehr unelegant) mit WindowsMovieMaker gelöst, der das Video richtig laden konnte.

    Annsonsten danke für die AVISynth Stunde, und ich hoffe ich kann mich weiterhin an dich wenden wenn ich Fragen habe.
  • Sephron schrieb:

    Eine Frage habe ich aber noch: Warum croppst du das Video vor dem Resize?


    Warum? Willste es dir selbst durch den Kopf gehen lassen warum man das so machen sollte? ;D

    Stell dir vor:
    Du hast ein 16:9 Video auf nem 4:3 Bild. Sprich dein Video hat schwarze Ränder. Jetzt lässte es aber auf 1920x1080 hochskalieren und cropst dann den schwarzen Rand weg. Dann haste aber gewiss keine 1920x1080 mehr, sondern irgend eine Auflösung die darunter fällt.

    Wenn du es vorher croppen tust, hast du eine in 16:9 befindliche Größe und resized dann auf 1920x1080. Zum einen muss der Skalierer den schwarzen Rand nicht mit skalieren, zum anderen wirst du die komplette 1920x1080 Auflösung damit haben, da du gewiss nicht mehr croppen tust.

    Um halt nicht 2mal zu skalieren oder auf irgendeine komische Auflösung zu kommen wird halt zuerst geroppt und dann skaliert.

    Die Resizer haben auch eine eingebaute Cropfunktion drin. Die Croppen auch alle vor dem eigentlichen Resize.