Avatar billede para7 Nybegynder
11. oktober 2012 - 08:55 Der er 52 kommentarer og
1 løsning

Få længden af et mp4 klip online

Jeg har et site der afspiller videoklip som mp4 i Flowplayer. Jeg kunne godt tænke mig, at der var en måde at aflæse klippenes længde online, så det kunne skrives i detaljerne om klippet, før man klikkede på det for at se klippet. Er det mon muligt?
Avatar billede softspot Forsker
11. oktober 2012 - 09:02 #1
Du kunne kaste dig over ffmpeg. Der burde være en mulighed for at trække oplysningerne ud af et videoklip med dette program.
Avatar billede para7 Nybegynder
11. oktober 2012 - 09:30 #2
Jeg kan ikke rigtig blive klog på den online player, for det er også noget video software. Alle mine sites er opbygget med Flowplayer. Hvis du mener, at måske ved ombygning med ffmpeg player, så kunne det være muligt at få hentet et klips længde ud til brug i ASP, og hvis du ved mere, sig gerne til...
Avatar billede softspot Forsker
11. oktober 2012 - 09:41 #3
Min tanke var egentlig kun, at du skulle bruge ffmpeg til at hente oplysningerne om videoklippet ud af klippet og gemme disse i din database, sammen med de øvrige oplysninger. Resten burde kunne fungere som hidtil.

Udfordringen med ffmpeg er blot at den kører som en kommandolinje applikation, så derfor skal du nok omkring en shell og noget med at tolke på en fil som ffmpeg genererer, men det burde være til at løse.

Jeg har ikke kendskab til andre løsninger (men der findes jo nok nogle), hvor man kan opnå det samme uden at skulle igennem dette.

Jeg prøver lige at lure på ffmpeg, for at se om jeg kan finde noget mere konkret til dig...
Avatar billede softspot Forsker
11. oktober 2012 - 10:05 #4
OK, faktisk findes informationen i det ffmpeg spytter ud, hvis du blot skriver:

ffmpeg -i din_video.mp4


Så skal vi bare have aktiveret ffmpeg fra ASP, så den kan fortælle os lidt om din video. Jeg forestiller mig noget i stil med dette:

dim ffmpegsti
dim ws
dim fso
dim videosti, tempOutput 

tempOutput = Server.MapPath("/") & "\temp\videoinfo.txt"
videosti = "stien til din video-fil"

set fso = Server.CreateObject("Scripting.FileSystemObject")
ffmpegsti = fso.GetParentFolderName(Server.MapPath("/")) & "\bin\ffmpeg.exe"
set fso = nothing
 
set ws = CreateObject("WScript.Shell")
ws.run ffmpegsti & " -i """ & videosti & """ > """ & tempOutput & """"
set ws = nothing

Herefter burde det være en form sag, at læse og fortolke den fil, som tempOutput peger på, mhp. at finde "Duration"...
Avatar billede softspot Forsker
11. oktober 2012 - 10:35 #5
Hvis det ikke fungerer med omdirigeringen af output, som vist i #4, kunne det være du havde mere held med denne metode:

Dim ffmpegCommand
ffmpegCommand = ffmpegsti & " -i """ & videosti & """ > """ & tempOutput & """"

Set objShell = Server.CreateObject("WScript.Shell")
Set objWshScriptExec = objShell.Exec(ffmpegCommand)
Set objStdOut = objWshScriptExec.StdOut

While Not objStdOut.AtEndOfStream
  strLine = objStdOut.ReadLine
  If InStr(strLine,"Duration") Then
      ' fortolk linjen og find info om varigheden af videoen...
  End If
Wend

Jeg har (heller) ikke selv testet denne udgave...
Avatar billede para7 Nybegynder
11. oktober 2012 - 13:14 #6
Tak indtil videre softspot

Har jeg fotstået det sådan, at ffmpeg scripting, har nogle muligheder, som måske kan hente længden af et klip, der vel at mærke ligger online på en webserver. Altså et mp4 h.264 kodet streaming klip?
Avatar billede softspot Forsker
11. oktober 2012 - 14:50 #7
Jeg ved ikke lige hvad ffmpeg scripting er for noget. Det jeg har benyttet mig af, er ffmpeg's kommandolinjeinterface til at aflæse nogle oplysninger om en video-fil. Da ffmpeg er et kommandolinjeværktøj, er det så nødvendigt at starte en kommandoprompt fra det miljø, hvori programmet skal bruges (hvis altså miljøet ikke i forvejen er kommandolinje :-)). I ASP kan man bruge WScript.Shell, i andre miljøer gøres det måske på andre måder...
Avatar billede para7 Nybegynder
11. oktober 2012 - 16:31 #8
OK, men altså ingen løsning til online brug endnu. Det kan jo komme en dag.
Avatar billede softspot Forsker
11. oktober 2012 - 18:30 #9
Jo, det er da en løsning til online brug!?

Det er jo lavet i ASP + VBScript som kører på en server, så jeg forstår ikke din konklusion...
Avatar billede para7 Nybegynder
11. oktober 2012 - 18:52 #10
OK, det kan jeg godt se af scriptet. Men jeg er på bar bund ang. implementering. Den ffmpeg player, jeg har forsøgt at finde een som kører streaming... ffmpeg.org er en meget nørdet side.
Avatar billede para7 Nybegynder
11. oktober 2012 - 18:57 #11
Ja undskyld at jeg ikke lige fatter det. Jeg laver et projekt, og er snart ved afslutningen, har brugt usansynlig meget tid på research. Men at få hentet duration, ville være et stort plus. Vel at mærke duration skal kunne hentes og vises på en klipliste, hvorfra man starter klippet.
Avatar billede softspot Forsker
11. oktober 2012 - 19:49 #12
Du skal ikke skifte player. Du skal ikke ændre noget i det du har lavet. Du skal bare tilføje den viste stump kode i forbindelse med at videoen lægges på sitet. Jeg ved i sagens natur ikke hvordan det foregår og hvornår, men når det sker, køres koden altså på videofilen og de data der kommer ud af det, skal du gemme sammen med  de øvrige oplysninger om videoen. Efter varigheden er aflæst med ffmpeg, kommer videoen i princippet ikke kontakt med ffmpeg igen og din video kan afspilles i samme afspiller som du hele tiden har benyttet.
Avatar billede para7 Nybegynder
11. oktober 2012 - 21:27 #13
OK. Det må jeg vist se lidt nærmere på.

ffmpegsti = fso.GetParentFolderName(Server.MapPath("/")) & "\bin\ffmpeg.exe"
Det ser ud til at ffmpeg.exe er en fil, der skal ligge på webserveren. Det er vel så noget jeg skal spørge om vores host TeamNetHosting kan installere?

Jeg har googlet om det, og kommer ikke nærmere end:
http://forum.videohelp.com/threads/346109-Streaming-with-FFMPEG
Avatar billede para7 Nybegynder
11. oktober 2012 - 21:28 #14
For ffmpeg er vel software, der skal installeres på webserveren.
Avatar billede softspot Forsker
11. oktober 2012 - 22:00 #15
Egentlig skal du nok mest af alt have ffmpeg.exe lagt i en mappe, hvor du har eksekveringsrettigheder, for selve ffmpeg findes i en udgave, der blot kan køres uden forudgående installation.
Avatar billede para7 Nybegynder
12. oktober 2012 - 18:26 #16
Har fået lagt filer som beskrevet og prøvet med de to eksempler. Når jeg kører i roden af localhost, er der ingen shell fejl med at filen ikke bliver fundet.

Men der sker ingenting...

Her er de to kodeeksempler:


tempOutput = Server.MapPath(".") & "\temp\videoinfo.txt"
Response.write "tempOutput: " & tempOutput & "<br>"
videosti = Server.MapPath(".") & "\video.mp4"
Response.write "videosti: " & videosti & "<br>"
set fso = Server.CreateObject("Scripting.FileSystemObject")
ffmpegsti = fso.GetParentFolderName(Server.MapPath(".")) & "\wwwroot\bin\ffmpeg.exe"
Response.write "ffmpegsti: " & ffmpegsti & "<br>"
set fso = nothing
set ws = CreateObject("WScript.Shell")
ws.run ffmpegsti & " -i """ & videosti & """ > """ & tempOutput & """"
set ws = nothing


tempOutput = Server.MapPath(".") & "\temp\videoinfo.txt"
Response.write "tempOutput: " & tempOutput & "<br>"
videosti = Server.MapPath(".") & "\video.mp4"
Response.write "videosti: " & videosti & "<br>"
'Response.end
set fso = Server.CreateObject("Scripting.FileSystemObject")
ffmpegsti = fso.GetParentFolderName(Server.MapPath(".")) & "\wwwroot\bin\ffmpeg.exe"
Response.write "ffmpegsti: " & ffmpegsti & "<br>"

ffmpegCommand = ffmpegsti & " -i """ & videosti & """ > """ & tempOutput & """"
Response.write "ffmpegCommand: " & ffmpegCommand & "<br>"
Set objShell = Server.CreateObject("WScript.Shell")
Set objWshScriptExec = objShell.Exec(ffmpegCommand)
Set objStdOut = objWshScriptExec.StdOut

While Not objStdOut.AtEndOfStream
  strLine = objStdOut.ReadLine
  If InStr(strLine,"Duration") Then
      ' fortolk linjen og find info om varigheden af videoen...
      Response.write "Duration skal findes her..."
  Else
      Response.write "Ikke fundet... Bliver ikke udskrevet heller..."
  End If
Wend
Avatar billede softspot Forsker
13. oktober 2012 - 17:22 #17
Du refererer ikke til roden, men den aktuelle mappe (hvadend det så er for en) og det er i kke hensigtsmæssigt. Referer derfor til roden eksplicit.

Med udgangspunkt i din egen kode (eksempel 2), ville jeg prøve flg.:

videosti = Server.MapPath("/video.mp4")
set fso = Server.CreateObject("Scripting.FileSystemObject")
ffmpegsti = Server.MapPath("/bin/ffmpeg.exe")

ffmpegCommand = ffmpegsti & " -i """ & videosti & """"

Set objShell = Server.CreateObject("WScript.Shell")
Set objWshScriptExec = objShell.Exec(ffmpegCommand)
Set objStdOut = objWshScriptExec.StdOut

While Not objStdOut.AtEndOfStream
  strLine = objStdOut.ReadLine
  If InStr(strLine,"Duration") Then
      ' fortolk linjen og find info om varigheden af videoen...
      Response.write "Duration skal findes her..."
  Else
      Response.write "Ikke fundet... Bliver ikke udskrevet heller..."
  End If
Wend

Jeg har rettet referencerne til stierne og undladt, at omdirigere output fra kaldet til ffmpeg til en fil, da det output jo nu læses direkte fra shell objektets stdout-egenskab (der er altså ikke længere behov for en midlertidig fil til at opsamle output).

Lad mig høre hvor det bringer dig hen...
Avatar billede para7 Nybegynder
13. oktober 2012 - 18:03 #18
Tak igen. Det prøver jeg i morgen...
Avatar billede para7 Nybegynder
14. oktober 2012 - 15:06 #19
Stierne skulle nu være korrekte. MEN med ny kode, sker der intet. While Not objStdOut.AtEndOfStream løkken tilgås slet ikke. Og hvis jeg kalder ffmpeg.exe direkte, får jeg fejl-skiltet:
programmet kan ikke startes da avcodec-52.dll mangler på computeren. Prøv at installere programmet igen for at løse dette problem.
Jeg har så prøvet at downloade og kopier eavcodec-52.dll ind i forskellige windows foldere for dll'ere, uden held.
Jeg har bare fra starten kopieret ffmpeg.exe ind i bin folderen, fra en download af en sansynlig udgave af ffmpeg.exe.
Avatar billede softspot Forsker
14. oktober 2012 - 23:59 #20
Har du hentet en ffmpeg i en "static build"? Find dem her: http://ffmpeg.zeranoe.com/builds/

Jeg ved ikke om det løser problemet, men det skulle være en exe som indeholder alle afhængigheder, så du ikke burde installere noget (det duer jo heller ikke når det skal ligge på en webserver du ikke selv administrerer).
Avatar billede para7 Nybegynder
15. oktober 2012 - 10:29 #21
OK, med den statiske kommer der ikke fejl, når jeg kører den manuelt, der kommer en cmd et øjeblik. Men While Not objStdOut.AtEndOfStream løkken tilgås stadig ikke. Jeg ville naturligvis gerne betale mange flere point. Kan du muligvis demonstrere, at det virker på fx en side, som du uploader. Eller måske kræver det egentlig, at man har sin egen webserver, hvor man kan installere og teste.
Avatar billede softspot Forsker
15. oktober 2012 - 12:01 #22
Det lader til at ffmpeg ikke sådan uden videre bare skriver til stdout, så man skal åbenbart springe gennem lidt ringe for at få den til det. Prøv f.eks. med dette:

videosti = Server.MapPath("/video.mp4")
set fso = Server.CreateObject("Scripting.FileSystemObject")
ffmpegsti = Server.MapPath("/bin/ffmpeg.exe")

ffmpegCommand = ffmpegsti & " -i """ & videosti & """ -f mp4 pipe:1"

Set objShell = Server.CreateObject("WScript.Shell")
Set objWshScriptExec = objShell.Exec(ffmpegCommand)
Set objStdOut = objWshScriptExec.StdOut

While Not objStdOut.AtEndOfStream
  strLine = objStdOut.ReadLine
  If InStr(strLine,"Duration") Then
      ' fortolk linjen og find info om varigheden af videoen...
      Response.write "Duration skal findes her..."
  Else
      Response.write "Ikke fundet... Bliver ikke udskrevet heller..."
  End If
Wend

Der skal vist være overensstemmelse mellem filtypen og det du skriver i parameteren -f, f.eks. -f mp4 for mp4-format, -f avi for avi-format osv. Det er dog ikke noget jeg er afklaret med, men det er jo noget du kan prøve lidt af.

Jeg har forsøgt ovenstående princip i en VBScript-fil på min lokale maskine, så det er testet i nogen omfang, men om det rent faktisk fungerer på en webserver... ja, det finder du jo nok hurtigt ud af.
Avatar billede para7 Nybegynder
15. oktober 2012 - 12:42 #23
Desværre stadig blank skærm... Andre muligheder?
Avatar billede softspot Forsker
15. oktober 2012 - 16:35 #24
Det jeg umiddelbart kan komme i tanke om der kunne være galt er, hvis formatet i -f parameteren ikke stemmer ovenens med den faktisk video's format, for der oplevede jeg nemlig også at output var blankt, så prøv evt. med en video hvor du er helt sikker på codec og se om det så fungerer. Du kan evt. lave testen lokalt inden du tester det på serveren.

Du kan evt. tage udgangspunkt i dette VBScript:

videosti = "C:\temp\video.mp4"
ffmpegsti = "c:\temp\ffmpeg.exe"

ffmpegCommand = ffmpegsti & " -i """ & videosti & """ -f mp4 pipe:1"

Set objShell = CreateObject("WScript.Shell")
Set objWshScriptExec = objShell.Exec(ffmpegCommand)
Set objStdOut = objWshScriptExec.StdOut

cnt = 20
msg = ""
While Not objStdOut.AtEndOfStream and cnt > 0
  strLine = objStdOut.ReadLine

  If InStr(1, strLine, "Duration", vbTextCompare) > 0 Then
      ' fortolk linjen og find info om varigheden af videoen...
      msg = "Duration findes!"
      cnt = 0
  Else
      msg = msg & strLine & vbCrLf
  End If
  cnt = cnt - 1
Wend

objStdOut.Close

msgbox msg

Processen er:
- Lav en fil lokalt og kald den test.vbs
- Indsæt det ovenfor viste kode
- Tilret stier til ffmpeg og video og gem
- Dobbeltklikker på vbs-filen i stifinder

Hvis det fungerer skrives der noget i beskedboksen, ellers er den tom. Jeg har som sagt fået det til at fungere med dette script, så under de rigtige omstændigheder burde det også fungere for dig.

Hvis det så kommer til at fungere på din egen maskine, kan du jo prøve med de samme indstillinger på webserveren.
Avatar billede para7 Nybegynder
15. oktober 2012 - 17:25 #25
Tak igen. Men stadig blank. jeg har prøvet med lidt forskellige mp4 filer. Jeg ved at dem jeg anvender og har testet er beregnet til at streame i Flowplayer og har codec h.264.
Avatar billede softspot Forsker
15. oktober 2012 - 21:01 #26
Prøv at skifte StdOut ud med StdErr, altså ændre denne linje

Set objStdOut = objWshScriptExec.StdOut

med denne

Set objStdOut = objWshScriptExec.StdErr
Avatar billede softspot Forsker
15. oktober 2012 - 21:03 #27
Du skal i øvrigt nok tillade lidt flere linjer end 20, for ellers risikerer du at headerinformationen fylder mere end de 20 første linjer...
Avatar billede softspot Forsker
15. oktober 2012 - 21:14 #28
Du skal muligvis tage højde for at stdout og stderr bufferne bliver fyldt og dermed vil få din kode til at hænge. Du kan finde en løsning på problemet her: http://support.microsoft.com/kb/960246
Avatar billede softspot Forsker
15. oktober 2012 - 21:15 #29
Du kan vist endda også nøjes med denne linje til definition af ffmpegCommand:

ffmpegCommand = ffmpegsti & " -i """ & videosti & """"
Avatar billede para7 Nybegynder
16. oktober 2012 - 07:39 #30
Med
Set objStdOut = objWshScriptExec.StdErr
Ca. 30 gange vises:
Ikke fundet... Bliver ikke udskrevet heller...Ikke fundet... Bliver ikke udskrevet heller...

Ved vi nu mere om, hvad der kan prøves? Eller må vi give op her?
Avatar billede softspot Forsker
16. oktober 2012 - 08:48 #31
Du er da kommet meget nærmere et resultat, idet der rent faktisk læses noget output fra ffmpeg! Nu skal du blot have læst hele resultatet af stdout OG stderr og fundet Duration.

Hvis du prøver at lure på det link jeg refererede til, kan du se hvordan du skal læse begge dele fuldt ud. Derefter burde det jo være en form sag at tolke det output...
Avatar billede softspot Forsker
16. oktober 2012 - 08:49 #32
Du kunne jo evt. prøve at udskrive det der rent faktisk læses i stedet for at skrive generiske tekster, så kunne det være det var mere åbenlyst for dig, hvor tæt du rent faktisk er målet.
Avatar billede para7 Nybegynder
16. oktober 2012 - 15:50 #33
Jeg ahr nu været igennem linkets forklaring og eksempler. Fx  har jeg testet med følgende, som giver fejl "Et objekt er obligatorisk: 'WScript' "

Set WSHShell = CreateObject("WScript.Shell")
Set oExec = WSHShell.Exec("cscript scriptworker.vbs")
With oExec
  Do While .Status = 0
      WSHShell.Sleep 10
      Do While Not .StdOut.AtEndOfStream
        WScript.Echo .StdOut.ReadLine
         
        'Check the .StdErr to see if it is at the end of its
          'stream. If not, call ReadLine on it
          If Not .StdErr.AtEndOfStream Then
            .StdErr.ReadLine
          End If
      Loop
    Loop
End With

Jeg kan forstå hvordan parent og child objecterne virker, men kan ikke få det til at virke.

Hvad gør vi?
Avatar billede para7 Nybegynder
16. oktober 2012 - 15:52 #34
Har også prøvet at uploadet det hele til serveren, men får Access denied. Har ikke lige adgang til at tillade kørsel af ffmpeg.exe, men det skal vel og så køre lokalt først.
Avatar billede softspot Forsker
16. oktober 2012 - 16:24 #35
Det var meningen at du skulle bruge linket som inspiration til at tilpasse det vi var kommet frem til ikke bruge det kode der var vist...

Grunden til at du får fejlen er, at der refererer til en variabel, som ikke er erklæret eller instantieret (den variabel du ønsker at bruge hedder WSHShell og ikke WScript), men det er som nævnt lidt ligegyldigt ifht. den løsning du skal arbejde hen mod :-)

Det du skal fokusere på, er måden det med læsning af stdOut og stdErr er løst på, dvs. løkke i løkke med Sleep og læsning af de to buffere for at undgå at disse fyldes op. Resten skal være som det hidtil har været (#24 + patch fra #26, #27 og #29).
Avatar billede para7 Nybegynder
16. oktober 2012 - 19:22 #36
ok, og tak igen, men det er lidt som russisk for mig. Er det noget i den her retning?

Do While .Status = 0
    objShell.Sleep 10
    While Not objStdOut.AtEndOfStream
      strLine = objStdOut.ReadLine
      If InStr(strLine,"Duration") Then
          ' fortolk linjen og find info om varigheden...
          Response.write "Duration skal findes her..."
      Else
          Response.write "Den gik ikke..."
      End If
    Wend
Loop
Avatar billede softspot Forsker
16. oktober 2012 - 21:06 #37
Nederst har jeg udfærdiget et script som er testet og kører lokalt på min maskine. Prøv lige at klippe scriptet ud og læg det i en ny fil (kald den f.eks. test.vbs). Placér den sammen med din testvideo (f.eks. video.mp4) og ffmpeg-programmet. Aktivér scriptet ved, fra en commandoprompt, at skifte til mappen med de 3 filer og skriv så:

test video.mp4

Scriptet ser således ud:

option explicit

dim vsti, ffsti, objFac

vsti = WScript.Arguments(0)
ffsti = "ffmpeg.exe"
set objFac = GetRef("ObjectFactory")

msgbox vsti & vbCrLf & _
      "Duration: " & FindVideoDuration(vsti, ffsti, objFac)


' =========================================================
' =========================================================
const strToFind = "Duration"

' =========================================================
' =========================================================
function FindVideoDuration(videosti, ffmpegsti, ObjFactory)
  dim ffmpegCommand
  dim objShell, objExec, objStdOut, objStdErr
  dim strDuration, strLine, strLineOut, strLineErr, strTemp

  ffmpegCommand = ffmpegsti & " -i """ & videosti & """"

  Set objShell = ObjFactory("WScript.Shell")
  Set objExec = objShell.Exec(ffmpegCommand)
  Set objStdOut = objExec.StdOut
  Set objStdErr = objExec.StdErr

  strTemp = ""
  strDuration = ""
  Do While objExec.Status = 0
    'WScript.Sleep 10
    Do While Not objStdOut.AtEndOfStream Or Not objStdErr.AtEndOfStream
      strLineOut = ""
      If Not objStdErr.AtEndOfStream Then
        strLineOut = objStdOut.ReadLine
      End If

      strLineErr = ""
      If Not objStdErr.AtEndOfStream Then
        strLineErr = objStdErr.ReadLine
      End If

      If InStr(1, strLineOut, strToFind, vbTextCompare) > 0 Then
        strLine = strLineOut
      ElseIf Instr(1, strLineErr, strToFind, vbTextCompare) > 0 Then
        strLine = strLineErr
      Else
        strLine = ""
      End If

      If InStr(1, strLine, strToFind, vbTextCompare) > 0 Then
        strDuration = GetDuration(strLine)
      End If
    Loop
  Loop

  objStdErr.Close
  objStdOut.Close

  FindVideoDuration = strDuration
end function

' =========================================================
' fortolk linjen og find info om varigheden af videoen...
' =========================================================
function GetDuration(str)
  dim re, m, res

  Set re = new RegExp
  re.Pattern = strToFind & "\: (\d{2}\:\d{2}\:\d{2}\.\d+)"
  re.IgnoreCase = true

  Set m = re.Execute(str)
  If m.Count > 0 Then
    res = m(0).SubMatches(0)
  End If

  GetDuration = res
end function


' =========================================================
' =========================================================
function ObjectFactory(PROGID)
  set ObjectFactory = CreateObject(PROGID)
end function
Avatar billede para7 Nybegynder
16. oktober 2012 - 21:51 #38
Det ser super ud. Så skulle det da virke for mig også. (Windows 7 Pro). Jeg får bare nogle start-fejl. Jeg tager lige toppen:

<%
option explicit

dim WScript, vsti, ffsti, objFac

vsti = WScript.Arguments(0)


1.
"Variablen er ikke defineret: 'WScript'"
Jeg definerede den, men fik så en anden fejl:
"Et objekt er obligatorisk: ''

/test3.asp, linje 6
"
Avatar billede para7 Nybegynder
16. oktober 2012 - 22:04 #39
Hov. Glem lige ovenstående post. Jeg fik ikke læst og fulgt dine anvisninger. ;)

Nu får jeg ved kørsel via cmd et fint lille skilt med Duration for klippet.
Så langt, så godt. Hvordan kører jeg det så via ASP?
Avatar billede softspot Forsker
16. oktober 2012 - 22:54 #40
Prøv at paste dette ind i en ASP-fil og kør det på webserveren (hvor video-filen, dvs. i eksemplet video.mp4, er placeret i roden af sitet og ffmpeg.exe er placeret i bin-mappen, som ligeledes ligger i roden af sitet):

option explicit

dim vsti, ffsti, objFac

vsti = Server.MapPath("/video.mp4")
ffsti = Server.MapPath("/bin/ffmpeg.exe")
set objFac = GetRef("ObjectFactory")

Response.Write vsti & "<br>" & _
      "Duration: " & FindVideoDuration(vsti, ffsti, objFac)


' =========================================================
' =========================================================
const strToFind = "Duration"

' =========================================================
' =========================================================
function FindVideoDuration(videosti, ffmpegsti, ObjFactory)
  dim ffmpegCommand
  dim objShell, objExec, objStdOut, objStdErr
  dim strDuration, strLine, strLineOut, strLineErr, strTemp

  ffmpegCommand = ffmpegsti & " -i """ & videosti & """"

  Set objShell = ObjFactory("WScript.Shell")
  Set objExec = objShell.Exec(ffmpegCommand)
  Set objStdOut = objExec.StdOut
  Set objStdErr = objExec.StdErr

  strTemp = ""
  strDuration = ""
  Do While objExec.Status = 0
    Do While Not objStdOut.AtEndOfStream Or Not objStdErr.AtEndOfStream
      strLineOut = ""
      If Not objStdErr.AtEndOfStream Then
        strLineOut = objStdOut.ReadLine
      End If

      strLineErr = ""
      If Not objStdErr.AtEndOfStream Then
        strLineErr = objStdErr.ReadLine
      End If

      If InStr(1, strLineOut, strToFind, vbTextCompare) > 0 Then
        strLine = strLineOut
      ElseIf Instr(1, strLineErr, strToFind, vbTextCompare) > 0 Then
        strLine = strLineErr
      Else
        strLine = ""
      End If

      If InStr(1, strLine, strToFind, vbTextCompare) > 0 Then
        strDuration = GetDuration(strLine)
      End If
    Loop
  Loop

  objStdErr.Close
  objStdOut.Close

  FindVideoDuration = strDuration
end function

' =========================================================
' fortolk linjen og find info om varigheden af videoen...
' =========================================================
function GetDuration(str)
  dim re, m, res

  Set re = new RegExp
  re.Pattern = strToFind & "\: (\d{2}\:\d{2}\:\d{2}\.\d+)"
  re.IgnoreCase = true

  Set m = re.Execute(str)
  If m.Count > 0 Then
    res = m(0).SubMatches(0)
  End If

  GetDuration = res
end function


' =========================================================
' =========================================================
function ObjectFactory(PROGID)
  set ObjectFactory = Server.CreateObject(PROGID)
end function
Avatar billede para7 Nybegynder
17. oktober 2012 - 08:43 #41
DET VIRKER. Der skulle også en ordentlig stak kode til. Men nu kan jeg bare kalde en funktion, og så få skrevet længden ind i databasen. Så er det bare at få det til at køre med exe tilladelse på webhostingen. Men det går nok.

Send endelig svar for point.
Avatar billede softspot Forsker
17. oktober 2012 - 08:48 #42
:-)
Avatar billede para7 Nybegynder
17. oktober 2012 - 08:54 #43
det kører også i andet en wwwroot. Jeg har uploaded det samme til den rigtige webserver, den ser ikke ser ud til at give access denied. Men foreløbig er der denne fejl:

WshShell.Exec error '800700c1'

C:\websider\domaene.dk\www\bin\ffmpeg.exe -i "C:\websider\domaene.dk\www\video.mp4" is not a valid Win32 application.

/test3.asp, line 29
Avatar billede softspot Forsker
17. oktober 2012 - 09:01 #44
Det er muligt at exe-filnavnet også skal i anførselstegn:

ffmpegCommand = """" & ffmpegsti & """ -i """ & videosti & """"
Avatar billede softspot Forsker
17. oktober 2012 - 09:01 #45
Det er også muligt at du ikke har eksekveringsrettigheder til mappen bin på din webserver...
Avatar billede softspot Forsker
17. oktober 2012 - 09:23 #46
Det er også muligt at du skal have lagt 32-bit versionen af ffmpeg på serveren (jeg antager du har kørt 64-bit versionen på din egen maskine)...
Avatar billede para7 Nybegynder
17. oktober 2012 - 09:31 #47
Det er sådan set klaret. Jeg placerede ffmpeg.exe i roden af webhostingen, og her må den åbenbart godt exekveres. Måske det er hensigsmæssigt at få den lidt af vejen.

PS: Sjovt nok, kan jeg fra localhost undersøge længden på videofiler der ligger på webserveren... Meget praktisk, så kan scriptet også kkøre, når jeg tester lokalt.

Men ellers: Mission accomplished
Avatar billede softspot Forsker
17. oktober 2012 - 09:36 #48
Ja, jeg ville nok også prøve at få den helt væk fra sitets filstruktur (f.eks. i en mappe sidestillet med root på webserveren). Det er sjældent godt at have eksekverbare programmer tilgængeligt i sitestrukturen (med mindre der er taget specielle forholdsregler).
Avatar billede para7 Nybegynder
17. oktober 2012 - 10:03 #49
Hvis du lige er med lidt endnu... Har lige et lille problem.
Jeg lægger scriptet/funktionen ind i bunden af min conf fil. I den og på resten af sitet bruger jeg ikke option explicit, jeg synes det går fint uden, og koderne er mere overskuelige.
Når jeg fjerner det og dim i koden, får jeg en fejl (ikke når jeg kører scriptet seperat):

Der opstod en Microsoft VBScript-kompileringsfejl fejl '800a0411'

Navnet er omdefineret

/Frits Skov/nettv1.dk/Assets/KONFIGURATION.asp, linje 77

const strToFind = "Duration"
Avatar billede softspot Forsker
17. oktober 2012 - 10:18 #50
Jeg kan kun anbefale dig at bruge option explicit og at erklære din variable inden de bruges (med dim) og helst i det scope hvor de er relevante. Det giver dig en meget bedre mulighed for at fejlfinde, hvis du har stavet variabelnavne forkert, hvilket ellers kan være en pestillens at fejlfinde. Samtidig undgår du at komme til at overskrive andre variable med samme navn i det globale scope, som kan give nogle uventede sideeffekter, der igen er noget træls at fejlfinde på. Jeg er lidt forundret (og bekymret) over, at du bevidst vælger at sænke kvaliteten af din kode... :S

I dit konkrete tilfælde har du åbenbart allerede en anden variabel som hedder strToFind, så derfor kan du ikke definere en const med dette navn.
Avatar billede para7 Nybegynder
17. oktober 2012 - 10:20 #51
Det gør nu ikke noget. Jeg har fået det til at køre, der hvor jeg redigerer klippene, og det er jo fantastisk nok.

Så tak softspot for nu for en heltedåd :)
Avatar billede softspot Forsker
17. oktober 2012 - 10:46 #52
Velbekomme
Avatar billede para7 Nybegynder
17. oktober 2012 - 11:35 #53
Forstår bekymringen, men jeg har valgt option explicit fra for år tilbage. Det hjælper ikke mig, jeg kan let nok finde en fejl. Dog er de koder du har forsynet mig med, noget udover min forstand. Men mine sider kører hurtigt nok uden de formaliteter. Jeg er efterhånden gået over til PHP, og her er der ikke den slags omstændighder.
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester