WinFuture-Forum.de: [gelöst]Batch-Programmierung - WinFuture-Forum.de

Zum Inhalt wechseln

Nachrichten zum Thema: Entwicklung
Seite 1 von 1

[gelöst]Batch-Programmierung


#1 Mitglied ist offline   je77 

  • Gruppe: aktive Mitglieder
  • Beiträge: 27
  • Beigetreten: 25. Januar 18
  • Reputation: 0
  • Geschlecht:Männlich

geschrieben 26. Januar 2018 - 15:12

Hallo,
ich kann zwar (etwas) programmieren, aber ich benötige Hilfe für ein Batch-Script. Leider liegt mir die Batch-Programmierung nicht so und deswegen benötige ich etwas Hilfe. Ich benutze ffmpeg zum automatischen Schneiden von mp4-Dateien - es wird der Vorspann weggeschnitten und der Abspann. Dazu eignet sich ffmpeg ganz gut, da es kommandozeilenbasiert arbeitet und sich per Batch programmieren lässt.

Der erste Teil des Scripts ermittelt die Dauer ("geslaenge") aller mp4s im Ordner.

Die Filmlänge ("filmlaenge") = Dauer ("geslaenge") - Vorspann ("vor") - Abspann ("ab").

Dann möchte ich die Filmlänge ganzzahlig erhalten - ich addiere 1 dazu und teile durch 1 damit die Filmlänge die Nachkommastellen verliert und ganzzahlig wird.

Dann kommt der Teil in dem ffmpeg aufgerufen wird und die mp4s schneidet.

Wäre es möglich, dass jemand mal drüberschaut, der sich mit Batch-Programmierung auskennt und mir netterweise erklärt was ich falsch mache?

Ich komme nämlich allein nicht mehr weiter...

Das Script habe ich mir teilweise mit Hilfe und mit googlen zusammengebaut.

(Ursprünglich bestand es aus zwei Batchdateien, die mittels Text-Dateien, die Werte übergeben haben. Den Weg mit den Textdateien möchte ich nicht mehr verwenden.)

Nun bin ich dabei aus den zwei Dateien eine zu machen - und das ist der Versuch den ich hier poste:

@echo off
echo Vorspannlaenge eingeben
set/p vor=
echo Abspannlaenge eingeben
set/p ab=
SETLOCAL EnableDelayedExpansion

@echo off
set z=1
    for %%F in (*.mp4) do (
        for /f "tokens=2-5 delims=:., " %%a in (
            'ffmpeg -i "%%F" 2^>^&1 ^| find "Duration:"'
        ) do (
            setlocal enableDelayedExpansion
            set /a "geslaenge=1%%a*3600 + 1%%b*60 + 1%%c - 366100"
            echo geslaenge.%%d
		set/a filmlaenge=geslaenge - vor - ab
		set/a filmlaenge=filmlaenge+=1
		set/a filmlaenge=filmlaenge/1
		echo %filmlaenge%
		ffmpeg -i !z!.mp4 -ss !vor! -t %%filmlaenge -c:v copy -c:a copy "geschnitten\!z!.mp4"
		set /a z+=1
            endlocal
        )
    )
pause



Ich würde mich sehr freuen und bin sehr dankbar wenn mir jemand helfen könnte.

Viele Grüße,

je77
0

Anzeige



#2 Mitglied ist offline   RalphS 

  • Gruppe: VIP Mitglieder
  • Beiträge: 8.895
  • Beigetreten: 20. Juli 07
  • Reputation: 1.126
  • Geschlecht:Männlich
  • Wohnort:Zuhause
  • Interessen:Ja

geschrieben 26. Januar 2018 - 16:45

Muß es batch sein?

Schau Dir mal PowerShell an. Das kann nativ rechnen. Batch ist für sowas nicht geeignet.
"If you give a man a fish he is hungry again in an hour. If you teach him to catch a fish you do him a good turn."-- Anne Isabella Thackeray Ritchie

Eingefügtes Bild
Eingefügtes Bild
0

#3 _d4rkn3ss4ev3r_

  • Gruppe: Gäste

geschrieben 26. Januar 2018 - 16:54

setlocal enableDelayedExpansion ist doppelt. Am Anfang reicht es
endlocal kann daher auch weg.

Was ist mit dem Script? Fehler?

@RalphS: Wozu? Lieber per Batch als Powershell
0

#4 Mitglied ist offline   RalphS 

  • Gruppe: VIP Mitglieder
  • Beiträge: 8.895
  • Beigetreten: 20. Juli 07
  • Reputation: 1.126
  • Geschlecht:Männlich
  • Wohnort:Zuhause
  • Interessen:Ja

geschrieben 27. Januar 2018 - 03:21

Sagt ja keiner, daß man batch nicht nehmen kann. Aber für Arithmetik ist alles besser als Batch und es besteht kein Grund, eine Umgebung zu verwenden, die auf das Problem nur schlecht paßt. Besonders dann, wenn es welche gibt, die besser passen.

Und da dem TO Batch eh nicht liegt... vielleicht gefällt ihm PS ja besser. :)
"If you give a man a fish he is hungry again in an hour. If you teach him to catch a fish you do him a good turn."-- Anne Isabella Thackeray Ritchie

Eingefügtes Bild
Eingefügtes Bild
0

#5 Mitglied ist offline   je77 

  • Gruppe: aktive Mitglieder
  • Beiträge: 27
  • Beigetreten: 25. Januar 18
  • Reputation: 0
  • Geschlecht:Männlich

geschrieben 27. Januar 2018 - 18:17

Hallo,
danke an alle, die geantwortet haben!!
Jetzt läuft es!

@echo off
SETLOCAL EnableDelayedExpansion
echo Vorspannlaenge eingeben
set/p vor=
echo Abspannlaenge eingeben
set/p ab=
set geslaenge=0
set filmlaenge=0

set z=1
    for %%F in (*.mp4) do (
        for /f "tokens=2-5 delims=:., " %%a in (
            'ffmpeg -i "%%F" 2^>^&1 ^| find "Duration:"'
        ) do (
            set /a "geslaenge=1%%a*3600 + 1%%b*60 + 1%%c - 366100"
            set /a "geslaenge=geslaenge+1"
		set /a "filmlaenge=geslaenge - vor - ab"
		ffmpeg -i !z!.mp4 -ss !vor! -t !filmlaenge! -c:v copy -c:a copy "geschnitten\!z!.mp4"
		set /a z+=1
            )
    )
pause


0

#6 _d4rkn3ss4ev3r_

  • Gruppe: Gäste

geschrieben 28. Januar 2018 - 08:59

Dann markiere bitte den Thread als gelöst.
0

#7 Mitglied ist offline   je77 

  • Gruppe: aktive Mitglieder
  • Beiträge: 27
  • Beigetreten: 25. Januar 18
  • Reputation: 0
  • Geschlecht:Männlich

geschrieben 28. Januar 2018 - 10:49

Hallo,
leider habe ich doch noch ein Problem:

Die mp4-Dateien, die geschnitten werden sollen, haben eine variable Länge. Der Vor- und Abspann ist konstant. Ich lasse die Gesamtlänge jeder Datei ermitteln (geslaenge, kommt aus "Duration").
Die Filmlänge (variabel) = Gesamtlänge (variabel) - Vorspann (konstant) - Abspann (konstant).
Der Vorspann wird korrekt weggeschnitten - nur der Abspann wird mal zu früh, mal zu spät weggeschnitten.

Vielleicht weiß jemand woran das liegen kann?

Über Hilfe würde ich mich sehr freuen, es sind 169 Aufnahmen aus meiner Sammlung, die geschnitten werden sollen. Manuell ist das sehr aufwendig...
Ich bitte um Hilfe...

@echo off
SETLOCAL EnableDelayedExpansion
echo Vorspannlaenge eingeben
set/p vor=
echo Abspannlaenge eingeben
set/p ab=

set z=1
    for %%F in (*.mp4) do (
	set geslaenge=0
	set filmlaenge=0
        for /f "tokens=2-5 delims=:., " %%a in ('ffmpeg -i "%%F" 2^>^&1 ^| find "Duration:"')
        do (
            set /a "geslaenge=1%%a*3600 + 1%%b*60 + 1%%c - 366100"
            set /a "geslaenge=geslaenge+1"
                set /a "filmlaenge=geslaenge - vor - ab"
                ffmpeg -i !z!.mp4 -ss !vor! -t !filmlaenge! -c:v copy -c:a copy "geschnitten\!z!.mp4"
                set /a z+=1
            )
    )
pause


0

#8 _d4rkn3ss4ev3r_

  • Gruppe: Gäste

geschrieben 28. Januar 2018 - 12:50

Eventuell gibt es Probleme bei der Rechenaufgabe mittels set
Probiere das in einzelne Schritte zu teilen und gib jeweils immer danach das Ergebnis aus um Fehler zu entdecken
0

#9 Mitglied ist offline   je77 

  • Gruppe: aktive Mitglieder
  • Beiträge: 27
  • Beigetreten: 25. Januar 18
  • Reputation: 0
  • Geschlecht:Männlich

geschrieben 28. Januar 2018 - 19:49

 Zitat (RalphS: 27. Januar 2018 - 03:21)

Und da dem TO Batch eh nicht liegt... vielleicht gefällt ihm PS ja besser. :)


Hallo RalphS,

ich würde doch gerne Powershell mal testen, ist installiert.
Leider bekomme ich das Script nicht zum Laufen, da es nicht signiert ist. Online finde ich nur für mich Ungeübten nur schwere Anleitungen, die mir nicht viel sagen.

Ich kann Scripte für VBA Excel programmieren und möchte mein Vorhaben (automatisches schneiden mit ffmpeg) mal mit Powershell angehen...

Vielleicht wäre jemand so freundlich und könnte mir erklären was ich tun muss damit ich Powershellscripte ausführen kann.

Ich wünsche einen schönen Abend!

 Zitat (d4rkn3ss4ev3r: 28. Januar 2018 - 12:50)

Eventuell gibt es Probleme bei der Rechenaufgabe mittels set
Probiere das in einzelne Schritte zu teilen und gib jeweils immer danach das Ergebnis aus um Fehler zu entdecken


Hallo,

die Werte waren okay.

Ich werde mir Powershell ansehen, ob ich da programmier-technisch besser klar komme. Batch fällt mir schwer.

Schönen Abend...
0

#10 Mitglied ist offline   sklaes 

  • Gruppe: Mitglieder
  • Beiträge: 8
  • Beigetreten: 04. Dezember 04
  • Reputation: 0

geschrieben 28. Januar 2018 - 20:46

Damit du Skripte in der Powershell ausführen kannst musst du die ExecutionPolicy anpassen
Set-ExecutionPolicy unrestricted



$vor=Read-host "Vorspannlänge eingeben" # z.B.: "01:27:58.021"
$ab =Read-host "Abspannlänge eingeben"

#Umwandlung der Benutzereingabe in ein Datumsobjekt mit dem man rechnen kann
$VorDate=[datetime]::ParseExact("$vor", "hh:mm:ss.fff", $null)
$nachDate=[datetime]::ParseExact("$nach", "hh:mm:ss.fff", $null)

$filme=Get-item C:\Pfad-Zu-den-Filmen\*.mp4

foreach ($film in $filme)
{
	$RawDuration=$(.\ffmpeg -i $($Film.Fullname)) | where {$_ -match "Duration:"}  # Folgender Aufbau angenommen:   Duration: 00:39:43.08, start: 0.040000, bitrate: 386 kb/s
	$Duration=$($RawDuration.Trim().Split(' ')[1]).TrimEnd(',') # inhalt in der Varibale nach dieser Zeile: "00:39:43.08"
	[int[]]$DurationSplit=$Duration.Split(':.')
	
$gesamtLaenge=get-date -Hour $DurationSplit[0] -Minute $DurationSplit[1] -Second $DurationSplit[2] -Millisecond $DurationSplit[3]
	
	$filmlaenge=$gesamtLaenge-$vorDate-$nachDate
	
	$parentDir=Split-Path "$Film" -Parent
	$(.\ffmpeg  -i $($Film.Fullname) -ss $vor -t $($filmlaenge.ToString("HH:mm:ss.fff")) -c:v copy -c:a copy "$parentDir\geschnitten\$($film.Name)")
}


Der Quelltext ist ungetestet und soll dir nur als Vorlage dienen

Dieser Beitrag wurde von sklaes bearbeitet: 28. Januar 2018 - 21:21

1

#11 Mitglied ist offline   je77 

  • Gruppe: aktive Mitglieder
  • Beiträge: 27
  • Beigetreten: 25. Januar 18
  • Reputation: 0
  • Geschlecht:Männlich

geschrieben 28. Januar 2018 - 22:03

Hallo sklaes,
Vielen Dank für deine Mühe!
Ich werde erstmal noch mit verschiedenen Programmiersprachen tüfteln.
Danke für das signing.
0

#12 Mitglied ist offline   RalphS 

  • Gruppe: VIP Mitglieder
  • Beiträge: 8.895
  • Beigetreten: 20. Juli 07
  • Reputation: 1.126
  • Geschlecht:Männlich
  • Wohnort:Zuhause
  • Interessen:Ja

geschrieben 29. Januar 2018 - 07:52

Ich weiß nicht recht. Denke, da steckt irgendwo anders noch ein Würmli drin. :unsure:

Sehe zumindest spontan nichts in der Logik, was da fehlerhaft sein könnte (ohne Gewähr); daher würd ich vorschlagen, erstmal die Übergabe an ffmpeg mit einem echo zu versehen (damit die Ausführung der Batchdatei die einzelnen Befehle ausgibt). Das irgendwo hinschreiben.

Und dann gucken. Was passiert, wenn man einen dieser Befehle ausführt? "Irgendwann" wird man wohl an etwas kommen, wo nicht wie erwartet geschnitten wird, und dann müßte man schauen, ob das was man dem ffmpeg-Befehl gefüttert hatte, das war, wo mach dachte (noch denkt) mit dem übereinstimmt, was man kriegt.


Ich hab nämlich so die Befürchtung, daß ffmpeg das "Problem" ist, bzw dessen Parametrisierung.

Re: PowerShell, man muß halt dran denken, daß PS nicht Batch ist und nicht prozedural, sondern objektorientiert arbeitet. Außerdem hat man mit PS Zugriff auf .NET-Objekte - unter anderem Windows Media.


So in etwa könnte man das angehen:

Function Process-AudioData
{ 
  [cmdletbinding()]
  Param
  (
    [Parameter(HelpMessage= 'Vorspannlänge eingeben' <# z.B.: "01:27:58.021"#>, Mandatory=$true)] [timespan] $Vorspannlaenge,
    [Parameter(HelpMessage= 'Abspannlänge eingeben', Mandatory=$true)] [timespan] $Abspannlaenge
  )    

  [IO.FileInfo[]] $filme = Get-ChildItem -Path 'C:\Pfad-Zu-den-Filmen' -Recurse -Filter '*.mp4' # -Recurse für Unterverzeichnisse; sonst kann es raus


  # Den Aufruf von ffmpeg, um Informationen zu erhalten, kann man sich an dieser Stelle sparen, wenn man auf Windows' eigenes Multimediasystem zurückgreift
  # Und nicht vergessen zu typisieren! 
  
  [Windows.Media.MediaPlayer] $wmp = [Windows.Media.MediaPlayer]::new()
  
  

  $filme|
   % {
     [IO.FileInfo] $thisFile = $_
     [uri] $thisFileURI = $thisFile.FullName
     $wmp.Open($thisFileURI)
     [timespan] $rawDuration =  if($wmp.NaturalDuration.HasTimeSpan) { $RawDuration= $wmp.NaturalDuration.TimeSpan}
        
     <#
         # jetzt kann mit den beiden Eingabeparametern $vor und $abspannlänge und $rawDuration auf TIMESPAN-Basis gerechnet werden (note: timespan ist kein Datum, sondern ein Zeitintervall)
         # dann muß nur noch das Parameterset für ffmpeg zusammengebaut werden
         # Formatierung in PS geht mit TEMPLATE -f PARAMETER, zB so:
     #>
        
     [string] $itemStart = '{0:D2}:{1:D2}:{2:D2}' -f $rawDuration.Hours, $rawDuration.Minutes,$rawDuration.Seconds
     
     <#
         # ... wobei die Zahl vorm Doppelpunkt die Parameter-ID ist (bei 0 angefangen) und alles incl Doppelpunkt optional ist; 
         # in diesem Fall sagt das D "Zahl"  und die 2 "soviele Stellen", sodaß man für zB 
         # '{0:d2}' -f 1
         # als Ergebnis 
         # 01
         # bekommt.
      #>
      
      # Hinterher Schließen nicht vergessen
      $wmp.Close()
      
      } # For-Each file
    } # Function 
    
    # "Normal" wird dies so eine Funktion, die ein ein Modul eingesetzt werden kann oder die mit . DATEINAME in die Umgebung geholt werden kann
    # Mit dem Aufruf kann man die Datei auch in PS ausführen lassen; diese ist dann schlau genug, angegebene Parameter selber aufzulösen und anzufordern (wegen Mandatory=$true).s
Process-AudioData



Natürlich unvollständig, nur erstmal als Startpunkt.

In PS kann man sich alles auf den Bildschirm geben, indem man das einfach hinschreibt. Das gilt für Zeichenfolgen und Zahlen ebenso wie für Objekte. $variable|gm zeigt Eigenschaften und Methoden an. $variable|fl * die Werte der Eigenschaften. Punkte sind Trennzeichen (wie gemeinhin üblich). Und $variable.Funktion (ohne Klammern) zeigt die möglichen Signaturen der Funktion. Also so:

[System.IO.FileInfo]::new

OverloadDefinitions                      
-------------------                      
System.IO.FileInfo new(string fileName)  
                                         



und dann kann man ohne größeren Aufwand sowas wie $datei = [IO.FileInfo]::new('C:\Dateiname.mp4') daraus ableiten.

Hilfe gibt es mit Get-Help und dem Namen des gesuchten cmdlets; get-command <name> -Syntax zeigt die Syntax dazu. Das funktioniert in den allermeisten Fällen.

PS schreibt sich eigentlich wie von selbst. Man muß nur erstmal den Zugang finden.
"If you give a man a fish he is hungry again in an hour. If you teach him to catch a fish you do him a good turn."-- Anne Isabella Thackeray Ritchie

Eingefügtes Bild
Eingefügtes Bild
0

#13 Mitglied ist offline   je77 

  • Gruppe: aktive Mitglieder
  • Beiträge: 27
  • Beigetreten: 25. Januar 18
  • Reputation: 0
  • Geschlecht:Männlich

geschrieben 29. Januar 2018 - 18:12

Hallo RalphS,

vielen Dank für die Mühe, die du dir gemacht hast!!

Der Fehler ist wahrscheinlich woanders:

Der Abspann ist doch nicht konstant sondern variiert manchmal um ein paar Sekunden!! Das habe ich bei den 169 Folgen nicht gleich gemerkt... (Der Vorspann ist wirklich konstant.)

Deswegen ist es wahrscheinlich auch klar warum ffmpeg "falsch" schneidet.
Ich sortiere gerade die Folgen in verschiedene Ordner (nach Abspannlänge) und führe dann die Schnittprozedur mit jeweils den richtigen Abspannlängen durch.

Dann denke ich, dass ffmpeg korrekt schneidet - schließlich habe ich, als die Schnittprozedur noch aus 2 Batches bestand, schon korrekt mit ffmpeg geschnitten.

Ich wünsche dir einen schönen Abend - und danke nochmals!

Viele Grüße, je77

Achja,
die Werte für die Gesamtfilmlänge und der Filmlänge (mit echo ermittelt) waren korrekt - es wird wohl am Abspann gelegen haben.

Gruß, je77
0

#14 Mitglied ist offline   je77 

  • Gruppe: aktive Mitglieder
  • Beiträge: 27
  • Beigetreten: 25. Januar 18
  • Reputation: 0
  • Geschlecht:Männlich

geschrieben 29. Januar 2018 - 21:27

Hallo,

jetzt ist es endgültig geschafft!!

Hier ist der lauffähige Code mit dem man mittels ffmpeg und Batch-Programmierung den Vor- und Abspann von Aufnahmen automatisch entfernen kann.

Vielen Dank an alle die mir geholfen haben!!

Gruß, je77

@echo off
SETLOCAL EnableDelayedExpansion
echo Vorspannlaenge eingeben
set/p vor=
echo Abspannlaenge eingeben
set/p ab=

    for %%F in (*.mp4) do (
        for /f "tokens=2-5 delims=:., " %%a in (
            'ffmpeg -i "%%F" 2^>^&1 ^| find "Duration:"'
        ) do (
            set /a "geslaenge=1%%a*3600 + 1%%b*60 + 1%%c - 366100"
		set /a "geslaenge=geslaenge+1"
                set /a "filmlaenge=geslaenge - vor - ab"
		ffmpeg -i %%F -ss !vor! -t !filmlaenge! -c:v copy -c:a copy "geschnitten\%%F"
         	)
    	)
pause


0

Thema verteilen:


Seite 1 von 1

1 Besucher lesen dieses Thema
Mitglieder: 0, Gäste: 1, unsichtbare Mitglieder: 0