다음 명령은 sed를 사용하여 youtube-dl의 출력을 처리하여 비디오의 파일 이름을 가져옵니다.
youtube-dl "$URL" 2> /dev/null | \
sed -n 's/^\[download\] Destination: //p; s/^\[download\] \(.*\) has already been downloade.*/\1/p'
youtube-dl이 HTML 가져오기 및 구문 분석을 마치고 비디오 다운로드를 시작한 직후(실행 시작 후 몇 초/초), 다운로드가 완료된 후 비디오의 파일 이름을 출력합니다(접미사에 재생 시간이 추가됨) .part
. 다운로드되었습니다)
그래서 문제의 핵심과 내가 막고 있는 것은 어떻게 위 명령을 백그라운드에 넣고(계속 다운로드되도록) 표준 출력에서 비디오 파일 이름을 가져와서 열 수 있느냐 하는 것입니다. 다운로드가 완료되기 전에 비디오 파일.
답변1
당신이 사용할 수있는 inotifywait
:
$ youtube-dl "$URL" &
$ inotifywait --event create --format '"%f"' . | xargs vlc
거기에는 경쟁 조건이 있습니다. 연결이 매우 빠른 경우(저는 그렇죠) 플레이어가 파일을 열기 전에 파일을 다운로드하고 이름을 바꿀 수 있습니다. 또한 youtube-dl
오디오와 비디오를 별도로 다운로드하는 등의 작업을 수행하면 잘못된 파일을 열 수도 있습니다.
답변2
@fra-san의 의견은 출력 라인을 한 줄씩/프로그래밍 방식으로 처리하는 데 사용할 수 있는 while read
루프를 생각나게 했습니다(기능적으로 파이프를 사용하는 대신). 연산자를 사용하여 <
파일의 출력을 다음 루프로 파이프 할 수 있습니다. youtube-dl 명령을 대체하는 Bash 프로세스를 사용하면 while 루프를 추가하여 백그라운드로 보낼 수도 있으며 &
while 루프는 여전히 출력을 읽을 수 있습니다(BPS에서 만든 파일만 읽음).
테스트를 통해 다운로드가 완료되고 이름이 변경된 후에도 비디오를 정상적으로 계속 재생할 수 있다는 것을 발견했습니다. 이는 mpv의 기능일 수 있습니다.
#!/bin/bash
# ytdl-stream - use youtube-dl to stream videos i.e watch videos as they download
# usage: ytdl-stream [YOUTUBE_DL_OPTIONS] URL
# you can pipe into it a command to open you video player, e.g:
# echo mpv --mute=yes | ytdl-stream -f 'best[width<=1920,height<=1080]' --write-auto-sub [URL]
test ! -t 0 && player_cmd="$(cat /dev/stdin)" || player_cmd="mpv"
while IFS="" read -r line; do
filename=$(echo "$line" | sed -n 's/^\[download\] Destination: //p')
if [[ -z "$filename" ]]; then
filename=$(echo "$line" | sed -n 's/^\[download\] \(.*\) has already been downloade.*/\1/p')
[[ -z "$filename" ]] && continue || notify-send "file already downloaded, opening.."
else
notify-send "downloading.."
fi
withoutExtensions="${filename%.*}"
withoutExtensions="${withoutExtensions%.*}"
if [[ -e "$filename" ]]; then
sleep 0.5 && ($player_cmd "$filename")&
elif [[ -e "$filename".part ]]; then
sleep 2
if [[ -e "$filename".part ]]; then
notify-send "found .part after sleep again"
($player_cmd "$filename".part)&
else
sleep 0.5 && ($player_cmd "$withoutExtensions"*)&
fi
fi
done < <(youtube-dl "$@" 2> /dev/null)&