Hallo,
Ik ben bezig met een project met webcams. Hiervoor is het nodig dat er een livestream wordt opgezet die via het web is te bekijken, middels flash. Nu hadden we in eerste instantie het idee om dit via een media server als wowza te doen, alleen blijkt dit heel erg moeilijk te worden omdat de camera die we hiervoor hebben niet het juiste MPEG4 formaat naar buiten stuurt (hij verstuurt MPEG4 part2 waar h.264 vereist is). Nieuwe camera's bestellen is helaas geen optie, dus moet het omgezet worden middels transcoding.
Via FFmpeg is het mogelijk live de stream om te zetten naar FLV, wat prima werkt. Nu wil ik alleen niet de webserver gebruiken van FFmpeg zelf, ivm security. Daarom had ik een PHP script gemaakt die de transcoding via FFmpeg start en de boel naar de browser stuurt. Dit werkt opzich wel redelijk, behalve dat PHP hiervoor niet snel genoeg lijkt te zijn. Het beeld blijft een lange tijd stil staan voor er wat gebeurd en als hij eenmaal begonnen is gaat het ook met horten en stoten.
Als alternatief heb ik hetzelfde scriptje in perl gemaakt, wat wel snel gaat. Probleem hiermee is alleen dat als de browser gesloten wordt, dat FFmpeg gewoon door blijft lopen, wat op langere termijn nogal een impact krijgt op de CPU load. In PHP kan je middels register_shutdown_function zorgen dat de boel netjes afgesloten wordt, maar in Perl bestaat die optie niet (of ik ken hem niet).
De vraag is dus, hoe kan ik er voor zorgen dat de stream gestopt wordt zodra de browser gesloten wordt?
Hier het perl scriptje:
En voor de geintresseerden ook het PHP script voor het geval daar een oplossing in te vinden is:
Ik ben bezig met een project met webcams. Hiervoor is het nodig dat er een livestream wordt opgezet die via het web is te bekijken, middels flash. Nu hadden we in eerste instantie het idee om dit via een media server als wowza te doen, alleen blijkt dit heel erg moeilijk te worden omdat de camera die we hiervoor hebben niet het juiste MPEG4 formaat naar buiten stuurt (hij verstuurt MPEG4 part2 waar h.264 vereist is). Nieuwe camera's bestellen is helaas geen optie, dus moet het omgezet worden middels transcoding.
Via FFmpeg is het mogelijk live de stream om te zetten naar FLV, wat prima werkt. Nu wil ik alleen niet de webserver gebruiken van FFmpeg zelf, ivm security. Daarom had ik een PHP script gemaakt die de transcoding via FFmpeg start en de boel naar de browser stuurt. Dit werkt opzich wel redelijk, behalve dat PHP hiervoor niet snel genoeg lijkt te zijn. Het beeld blijft een lange tijd stil staan voor er wat gebeurd en als hij eenmaal begonnen is gaat het ook met horten en stoten.
Als alternatief heb ik hetzelfde scriptje in perl gemaakt, wat wel snel gaat. Probleem hiermee is alleen dat als de browser gesloten wordt, dat FFmpeg gewoon door blijft lopen, wat op langere termijn nogal een impact krijgt op de CPU load. In PHP kan je middels register_shutdown_function zorgen dat de boel netjes afgesloten wordt, maar in Perl bestaat die optie niet (of ik ken hem niet).
De vraag is dus, hoe kan ik er voor zorgen dat de stream gestopt wordt zodra de browser gesloten wordt?
Hier het perl scriptje:
code:
1
2
3
4
5
6
7
8
9
10
11
| #!/usr/bin/perl -wT $| = 1; local $ENV{"PATH"} = "/bin:/usr/local/bin:/usr/bin"; local $ENV{"BASH_ENV"}=""; print "Pragma: no-cache\n"; print "Content-type: video/x-flv\n\n"; exec("/usr/bin/ffmpeg -er 4 -y -r 10 -b 320 -qmin 1 -qmax 3 -s 704x576 -an -bufsize 80000 -f rtsp -i rtsp://192.168.1.165:554/mpeg4/media.amp -f flv - 2> /dev/null"); |
En voor de geintresseerden ook het PHP script voor het geval daar een oplossing in te vinden is:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
| $descriptorspec = array( 0 => array("pipe", "r"), // stdin is a pipe that the child will read from 1 => array("pipe", "w"), // stdout is a pipe that the child will write to 2 => array("file", "/tmp/error-output.txt", "a") // stderr is a file to write to ); $cwd = '/tmp'; $process = proc_open('ffmpeg -er 4 -y -r 10 -b 320 -qmin 1 -qmax 3 -s 704x576 -an -bufsize 80000 -f rtsp -i rtsp://192.168.1.165:554/mpeg4/media.amp -f flv - 2> /dev/null', $descriptorspec, $pipes, $cwd); register_shutdown_function(array('flv_streamer', 'kill_stream'), $process); if (is_resource($process)) { // $pipes now looks like this: // 0 => writeable handle connected to child stdin // 1 => readable handle connected to child stdout // Any error output will be appended to /tmp/error-output.txt while (!feof($pipes[1])) { echo fgets($pipes[1]); ob_flush(); flush(); } // It is important that you close any pipes before calling // proc_close in order to avoid a deadlock $return_value = proc_close($process); } function kill_stream($process) { $status = proc_get_status($process); //close all pipes that are still open fclose($pipes[1]); //stdout fclose($pipes[2]); //stderr //get the parent pid of the process we want to kill $ppid = $status['pid']; //use ps to get all the children of this process, and kill them $pids = preg_split('/\s+/', `ps -o pid --no-heading --ppid $ppid`); foreach($pids as $pid) { if(is_numeric($pid)) { echo "Killing $pid\n"; posix_kill($pid, 9); //9 is the SIGKILL signal } } proc_close($process); } |