Running External Programs in windows

hello,
I’m trying to capture an image from a webcam using Windows 10.
I have FFmpeg install and I can capture an image using the cmd command:
ffmpeg -f dshow -video_size 1920x1080 -i "video=HD Pro Webcam C920" -frames:v 1 org_img.jpg.
What I fail doing is running this command using the run command in julia script.
I tried calling it as follow:

        mycmd = @cmd """ffmpeg -f dshow -video_size 1920x1080 -i "video=HD Pro Webcam C920" -frames:v 1 org_img.jpg"""
        run(`cmd /c $mycmd`)

but I get the following error

'ffmpeg' is not recognized as an internal or external command,
operable program or batch file.
ERROR: failed process: Process(`cmd /c ffmpeg -f dshow -video_size 1920x1080 -i 'video=HD Pro Webcam C920' -frames:v 1 org_img.jpg`, ProcessExited(1)) [1]

Stacktrace:
 [1] pipeline_error
   @ .\process.jl:525 [inlined]
 [2] run(::Cmd; wait::Bool)
   @ Base .\process.jl:440
 [3] run(::Cmd)
   @ Base .\process.jl:438
 [4] top-level scope
   @ REPL[13]:1

so I tried:

        run(mycmd)

and got the following error

ERROR: IOError: could not spawn `ffmpeg -f dshow -video_size 1920x1080 -i 'video=HD Pro Webcam C920' -frames:v 1 org_img.jpg`: no such file or directory (ENOENT)
Stacktrace:
 [1] _spawn_primitive(file::String, cmd::Cmd, stdio::Vector{Any})
   @ Base .\process.jl:99
 [2] #637
   @ .\process.jl:112 [inlined]
 [3] setup_stdios(f::Base.var"#637#638"{Cmd}, stdios::Vector{Any})
   @ Base .\process.jl:196
 [4] _spawn
   @ .\process.jl:111 [inlined]
 [5] run(::Cmd; wait::Bool)
   @ Base .\process.jl:439
 [6] run(::Cmd)
   @ Base .\process.jl:438
 [7] top-level scope
   @ REPL[17]:1

I found that VideoIO.jl can capture images from a Webcam, so I tried that to, and faild :frowning:

import VideoIO
cam = VideoIO.opencamera()

and got the following error

ERROR: MethodError: no method matching unsafe_convert(::Type{Ptr{Ptr{VideoIO.libffmpeg.AVDictionary}}}, ::VideoIO.AVDict)
Closest candidates are:
  unsafe_convert(::Type{Ptr{T}}, ::Base.ReshapedArray{T, N, P, MI} where {N, P<:AbstractArray, MI<:Tuple{Vararg{Base.MultiplicativeInverses.SignedMultiplicativeInverse{Int64}, N} where N}}) where T at reshapedarray.jl:281
  unsafe_convert(::Type{Ptr{T}}, ::LinearAlgebra.Transpose{var"#s832", var"#s831"} where {var"#s832", var"#s831"<:(AbstractVecOrMat{T} where T)}) where T at C:\buildbot\worker\package_win64\build\usr\share\julia\stdlib\v1.6\LinearAlgebra\src\adjtrans.jl:222
  unsafe_convert(::Type{Ptr{T}}, ::OffsetArrays.OffsetArray{T, N, AA} where {N, AA<:AbstractArray{T, N}}) where T at C:\Users\KOBIED\.julia\packages\OffsetArrays\I5Pfg\src\OffsetArrays.jl:454
  ...
Stacktrace:
 [1] avformat_open_input(ps::VideoIO.NestedCStruct{VideoIO.libffmpeg.AVFormatContext}, url::String, fmt::Ptr{VideoIO.libffmpeg.AVInputFormat}, options::VideoIO.AVDict)
   @ VideoIO.libffmpeg C:\Users\KOBIED\.julia\packages\VideoIO\EsW3Z\lib\libffmpeg.jl:8571
 [2] open_avinput(avin::VideoIO.AVInput{String}, source::String, input_format::Ptr{VideoIO.libffmpeg.AVInputFormat}, options::VideoIO.AVDict)
   @ VideoIO C:\Users\KOBIED\.julia\packages\VideoIO\EsW3Z\src\avio.jl:195
 [3] VideoIO.AVInput(source::String, input_format::Ptr{VideoIO.libffmpeg.AVInputFormat}, options::VideoIO.AVDict; avio_ctx_buffer_size::Int64)
   @ VideoIO C:\Users\KOBIED\.julia\packages\VideoIO\EsW3Z\src\avio.jl:218
 [4] VideoIO.AVInput(source::String, input_format::Ptr{VideoIO.libffmpeg.AVInputFormat}, options::VideoIO.AVDict)
   @ VideoIO C:\Users\KOBIED\.julia\packages\VideoIO\EsW3Z\src\avio.jl:207
 [5] opencamera(::String, ::Ptr{VideoIO.libffmpeg.AVInputFormat}, ::VideoIO.AVDict; kwargs::Base.Iterators.Pairs{Union{}, Union{}, Tuple{}, NamedTuple{(), Tuple{}}})
   @ VideoIO C:\Users\KOBIED\.julia\packages\VideoIO\EsW3Z\src\avio.jl:1016
 [6] opencamera(::String, ::Ptr{VideoIO.libffmpeg.AVInputFormat}, ::VideoIO.AVDict) (repeats 2 times)
   @ VideoIO C:\Users\KOBIED\.julia\packages\VideoIO\EsW3Z\src\avio.jl:1016
 [7] top-level scope
   @ REPL[20]:1

The VideoIO.jl documentation and examples are quite poor so I have no idea how to continue.
Please Help !!!

It’s probably missing the path to the ffmpeg executable. Try to provide the complete path to ffmpeg, e.g. in my case this works except that it doesn’t find the webcam :wink: :

julia> mycmd = @cmd """D:/Data/Downloads/ffmpeg-4.2.1-win64-static/bin/ffmpeg -f dshow -video_size 1920x1080 -i "video=HD Pro Webcam C920" -frames:v 1 org_img.jpg"""
`D:/Data/Downloads/ffmpeg-4.2.1-win64-static/bin/ffmpeg -f dshow -video_size 1920x1080 -i 'video=HD Pro Webcam C920'
 -frames:v 1 org_img.jpg`

julia> run(`cmd /c $mycmd`)
ffmpeg version 4.2.1 Copyright (c) 2000-2019 the FFmpeg developers
  built with gcc 9.1.1 (GCC) 20190807
...

thanks for the quick reply, that worked :tada: :tada:
I also found the FFMPEG.jl package, which did exactly as you suggested.

using MMFPEG
mycmd = @cmd """-f dshow -video_size 1920x1080 -i "video=HD Pro Webcam C920" -frames:v 1 org_img.jpeg"""
ffmpeg_exe(mycmd)

thanks again :slight_smile:

1 Like

Daniel, please do not be so quick to give up on VideoIO
In the early days VideoIO was a bear to use, I have done a lot of testing with it on Windows and found that it ‘just works’ now. Being honest I have not tried it for several months though , and not in 1.7

Johnh hello, on the contrary, I would be more then happy to be able to use the VidioIO.jl package.
Unfortunately I don’t understand way it’s not working. Using the run() command directly is a poor solution but it work for me.
If someone can help me with the VideoIO.jl package I’ll be more then happy to use it.
p.s. I’m working with julia v1.6

Update
Base.convert(::Type{Ref{Ptr{AVDictionary}}}, d::AVDict) = d.ref_ptr_dict
to
Base.cconvert(::Type{Ptr{Ptr{AVDictionary}}}, d::AVDict) = d.ref_ptr_dict

in avdictionary.jl which can be found at .julia/packages/videoio/somethingrandom/ src/avddictionary.jl , should start working hopefully