More robust device name parsing

This commit is contained in:
Alex Eidt 2021-12-27 22:25:33 -08:00
parent 7939e43840
commit 3fdb6a4808
3 changed files with 48 additions and 19 deletions

View file

@ -112,10 +112,9 @@ func NewCamera(stream int) *Camera {
panic("Unsupported OS: " + runtime.GOOS) panic("Unsupported OS: " + runtime.GOOS)
} }
camera := &Camera{name: device, depth: 3} camera := Camera{name: device, depth: 3}
getCameraData(device, camera) getCameraData(device, &camera)
return &camera
return camera
} }
func initCamera(camera *Camera) { func initCamera(camera *Camera) {

View file

@ -88,34 +88,65 @@ func webcam() string {
// For webcam streaming on windows, ffmpeg requires a device name. // For webcam streaming on windows, ffmpeg requires a device name.
// All device names are parsed and returned by this function. // All device names are parsed and returned by this function.
func parseDevices(buffer []byte) []string { func parseDevices(buffer []byte) []string {
devices := make([]string, 0)
bufferstr := string(buffer) bufferstr := string(buffer)
index := strings.Index(bufferstr, "DirectShow video device") index := strings.Index(strings.ToLower(bufferstr), "directshow video device")
if index == -1 { if index != -1 {
return devices
}
bufferstr = bufferstr[index:] bufferstr = bufferstr[index:]
}
index = strings.Index(bufferstr, "DirectShow audio device") index = strings.Index(strings.ToLower(bufferstr), "directshow audio device")
if index != -1 { if index != -1 {
bufferstr = bufferstr[:index] bufferstr = bufferstr[:index]
} }
type Pair struct {
name string
alt string
}
// Parses ffmpeg output to get device names. Windows only.
// Uses parsing approach from https://github.com/imageio/imageio/blob/master/imageio/plugins/ffmpeg.py#L681
pairs := []Pair{}
// Find all device names surrounded by quotes. E.g "Windows Camera Front" // Find all device names surrounded by quotes. E.g "Windows Camera Front"
r := regexp.MustCompile("\"[^\"]+\"") regex := regexp.MustCompile("\"[^\"]+\"")
matches := r.FindAllStringSubmatch(bufferstr, -1) for _, line := range strings.Split(strings.ReplaceAll(bufferstr, "\r\n", "\n"), "\n") {
for _, match := range matches { if strings.Contains(strings.ToLower(line), "alternative name") {
device := match[0][1 : len(match[0])-1] match := regex.FindString(line)
// Don't include Alternate Names for devices. if len(match) > 0 {
// Alternate names start with an '@'. pairs[len(pairs)-1].alt = match[1 : len(match)-1]
if !strings.HasPrefix(device, "@") { }
devices = append(devices, device) } else {
match := regex.FindString(line)
if len(match) > 0 {
pairs = append(pairs, Pair{name: match[1 : len(match)-1]})
}
}
}
devices := []string{}
// If two devices have the same name, use the alternate name of the later device as its name
for _, pair := range pairs {
if contains(devices, pair.name) {
devices = append(devices, pair.alt)
} else {
devices = append(devices, pair.name)
} }
} }
return devices return devices
} }
// Helper function. Array contains function.
func contains(list []string, item string) bool {
for _, i := range list {
if i == item {
return true
}
}
return false
}
// Parses the webcam metadata (width, height, fps, codec) from ffmpeg output. // Parses the webcam metadata (width, height, fps, codec) from ffmpeg output.
func parseWebcamData(buffer []byte, camera *Camera) { func parseWebcamData(buffer []byte, camera *Camera) {
bufferstr := string(buffer) bufferstr := string(buffer)

View file

@ -84,7 +84,6 @@ func NewVideoWriter(filename string, width, height int, options *Options) *Video
} else { } else {
writer.codec = options.codec writer.codec = options.codec
} }
return &writer return &writer
} }