Matin Lotfaliee
Matin Lotfaliee

Reputation: 1615

How to record a specific window using ffmpeg?

I use ffmpeg to record a window using this code:

ffmpeg.exe
-f dshow 
-y 
-i video="screen-capture-recorder":audio="virtual-audio-capturer":audio="Microphone (USB Audio Device)" 
-framerate 15 
-vcodec libx264 
-crf 0 
-preset ultrafast 
-acodec pcm_s16le 
-vf crop=Width:Height:Left:Top 
output.flv

But the problem is i might move the window, this leads to recording an area without the window i want.

How can i capture a specific window that I am able to move it?


Edit: I also used gdigrab to capture my window (Skype for instance) instead of dshow:

ffmpeg.exe
-y
-f dshow
-i audio="virtual-audio-capturer":audio="Microphone (USB Audio Device)"
-f gdigrab
-draw_mouse 0
-i title="Skype"
-framerate 30
-vcodec libx264
-crf 0
-preset ultrafast
-acodec pcm_s16le
output.flv

But the conference is black...

Upvotes: 30

Views: 61333

Answers (10)

Luca Pinelli
Luca Pinelli

Reputation: 176

on Ubuntu you can use the following script:

#!/usr/bin/env bash

echo "Please select the window that you want to record."

win_info="$(xwininfo)"
x="$(echo "$win_info" | grep -i 'absolute upper-left x' | sed 's/^[^0-9]*\([0-9]\+\)$/\1/g' )"
y="$(echo "$win_info" | grep -i 'absolute upper-left y' | sed 's/^[^0-9]*\([0-9]\+\)$/\1/g' )"
width="$(echo "$win_info" | grep -Ei '^\W+width:' | sed 's/^[^0-9]*\([0-9]\+\)$/\1/g' )"
height="$(echo "$win_info" | grep -Ei '\W+height:' | sed 's/^[^0-9]*\([0-9]\+\)$/\1/g' )"
now="$(date +%Y-%m-%d_%H-%M_%S)"

echo "
executing:

> ffmpeg -f x11grab -framerate 25 -video_size ${width}x${height} -i +${x},${y} "window_recording_${now}.mp4"

[press ctrl+c in this terminal to stop the recording]

"

ffmpeg -f x11grab -framerate 25 -video_size ${width}x${height} -i +${x},${y} "window_recording_${now}.mp4"

Upvotes: 0

Yamiel Serrano
Yamiel Serrano

Reputation: 124

In order to record a program of window, the "gdigrab" element is necessary together with its "title" complement, this being the name of the window as it is shown in -->task manager >> details, this in windows. enter image description here

ffmpeg -f gdigrab -rtbufsize 150M -i title="VisorATSC1" -s 480x360 -r 15 -b 2000k -minrate 2000k -maxrate 2000k -vcodec h264_nvenc -gpu 0 -f flv rtmp://x.x.x.x:1935/live/YASV

Upvotes: 2

amirmahdi nezhadshamsi
amirmahdi nezhadshamsi

Reputation: 108

I can't comment so write this here.
Brian Huang's answer gives this error for me:

width not divisible by 2 (603x585)
Error initializing output stream 0:0 -- Error while opening encoder for output stream #0:0 - maybe incorrect parameters such as bit_rate, rate, width or height

but after adding -vf scale=1280:720 with desired resolution which both height and width are even this error will disappear and screen recording will work. even if it's covered by other windows will not appear in recorded file.

Upvotes: 0

Lu Xu
Lu Xu

Reputation: 411

I improved the command from MaxC's answer.

One issue with that command is the region position does not consider multi-monitor layout. The x and y in geometry line is relative to the current monitor, so it can not record windows in other monitors.

The information are parsed form individual lines. And the window border is considered. Also added count down to let user be ready. Here is the script:

#!/bin/sh
xwininfo | {
    while IFS=: read -r k v; do
        case "$k" in
        *"Absolute upper-left X"*) x=$v;;
        *"Absolute upper-left Y"*) y=$v;;
        *"Border width"*) bw=$v ;;
        *"Width"*) w=$v;;
        *"Height"*) h=$v;;
        esac
    done
    for i in 3 2 1; do echo "$i"; sleep 1; done
    ffmpeg -y -f x11grab -framerate 30 \
           -video_size "$((w))x$((h))" \
           -i "+$((x+bw)),$((y+bw))" screenrecord.mp4
}

Two things I am not certain:

  • Absolute or Relative upper-left X/Y coordinates (see output of xwininfo)?
  • Does all the WM/DE give the window border info consistently, i.e., are x and y always referring to the point outside the window border?

Upvotes: 5

Grant E.
Grant E.

Reputation: 1

ffmpeg -f x11grab -framerate 25
$(xwininfo | gawk 'match($0, /-geometry ([0-9]+x[0-9]+).([0-9]+).([0-9]+)/, a)
{ print "-video_size " a[1] " -i +" a[2] "," a[3] }')
$(date +%Y-%m-%d_%H-%M_%S).mp4

This doesn't work on windows where xwininfo returns the "size" portion of the geometry in character cells instead of pixels (e.g. terminal windows). To fix this, the size needs to be extracted from the Width: and Height: fields of the xwininfo response.

Upvotes: 0

MaxC
MaxC

Reputation: 590

I was also looking for a solution online, but was not satisfied with the answers I found. I have now fiddled together this very simplistic solution for linux:

ffmpeg -f x11grab -framerate 25 \
    $(xwininfo | gawk 'match($0, /-geometry ([0-9]+x[0-9]+).([0-9]+).([0-9]+)/, a)\
      { print "-video_size " a[1] " -i +" a[2] "," a[3] }') \
    $(date +%Y-%m-%d_%H-%M_%S).mp4
  • After executing this command the window can be selected with the mouse pointer

  • The target filename will take the form YYYY-mm-dd_hh_mm_ss.mp4 in the current directory.

  • The awk magic there just parses the window info. It is ugly and only works with gnu awk, but I have not found a better way yet to parse the window geometry into a custom format.

The syntax to record a specific rectangle on screen is:

-video_size [width]x[height] -i [x],[y]

and should also work under windows and with dshow, I believe.

Upvotes: 18

Brian Huang
Brian Huang

Reputation: 51

ffmpeg -rtbufsize 1500M -f dshow -i audio="virtual-audio-capturer" -f gdigrab -framerate 30 -draw_mouse 1 -i title=RecordWindow -pix_fmt yuv420p -profile:v baseline -y Huangbaohua.mp4

the RecordWindow is the title of a specified window.

Upvotes: 3

PythonProgrammi
PythonProgrammi

Reputation: 23463

I used this to record the prompt

ffmpeg -rtbufsize 1500M -f dshow -i audio="Microfono (8- Logitech USB Headset)" -f gdigrab -framerate 30 -draw_mouse 1 -i title="Prompt dei comandi" -pix_fmt yuv420p -profile:v baseline -y output\output3_xp.mp4
pause

But it works only with 100x20 (colxrow) fo the prompt or other divisible screen size, otherwise it gives me an error, this:

[libx264 @ 0000027c7ed66200] width not divisible by 2 (269x432)
Error initializing output stream 0:0 -- Error while opening encoder for output stream #0:0 - maybe incorrect parameters such as bit_rate, rate, width or height
Conversion failed!

P.S.: I have this problem also with other windows that has not even width or height. I created a window with tkinter in Python and I get the error, then I gave the window some geometry (300x500) and it worked...

Strangely, the mouse is a little offset...

Upvotes: 0

Matin Lotfaliee
Matin Lotfaliee

Reputation: 1615

It has mentioned in here:

By default, it captures the "full screen" of the main desktop monitor (all windows, overlapping, from there, with aero if vista+, without transparent windows if non aero).

To configure it differently, run the provided "configuration setup utilities/shortcuts" or adjust registry settings before starting a run (advanced users only):

HKEY_CURRENT_USER\Software\screen-capture-recorder

with DWORD keys respected of start_XXX etc …​ (see the included file {installdir}\configuration_setup_utility\setup_screen_tracker_params.rb for the full list of registry key values available, or see https://github.com/rdp/screen-capture-recorder-to-video-windows-free/blob/master/configuration_setup_utility/setup_screen_tracker_params.rb#L9 )

ex: see configuration_setup_utility\incoming.reg file (though NB that those values are in hex, so editing that file is a bit tedious-- I always just use regedit or the accompanying script utilities and don’t edit it by hand).

To "reset" a value delete its key.

And you can see in here that there are these registery options:

  • capture_height
  • capture_width
  • start_x
  • start_y
  • default_max_fps
  • stretch_to_width
  • stretch_to_height
  • stretch_mode_high_quality_if_1
  • hwnd_to_track
  • disable_aero_for_vista_plus_if_1
  • track_new_x_y_coords_each_frame_if_1
  • capture_mouse_default_1
  • capture_foreground_window_if_1
  • dedup_if_1
  • millis_to_sleep_between_poll_for_dedupe_changes
  • capture_transparent_windows_including_mouse_in_non_aero_if_1_causes_annoying_mouse_flicker
  • hwnd_to_track_with_window_decoration

Upvotes: 4

Yurkol
Yurkol

Reputation: 1492

This example works for me:

ffmpeg -f gdigrab -framerate 30 -i title="german.avi - VLC media player" -b:v 3M  germ.flv

where "title" means actual title of a target window.

Hope this will help.

Upvotes: 13

Related Questions