Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: proc_open() i zapis do procesu
Forum PHP.pl > Forum > PHP
carbolymer
Składnia lame.exe:
Kod
E:\Pulpit\stream>lame -h
LAME 32bits version 3.98.2 (http://www.mp3dev.org/)

usage: lame [options] <infile> [outfile]

    <infile> and/or <outfile> can be "-", which means stdin/stdout.



Mam problem z konwertowaniem mp3. Używam lame, ale zamiast standardowego odczytu z pliku i zapisu do pliku, wolę użyć proc_open i pipe'y (uchwyty do plików, czy jakkolwiek to sie tłumaczy). Gdy podam zamiast wejścia - plik, wszystko działa jak trzeba:
  1. <?php
  2. $sCommand = 'lame.exe '.$sFile.' -'
  3. ?>

I otrzymuje na w $sPipe[1] poprawnie zakodowane dane.

Gdy podam zamiast wyjścia - plik, też działa jak trzeba:
  1. <?php
  2. $sCommand = 'lame.exe --mp3input - song.mp3';
  3. ?>

W stdin ląduje poprawnie piosenka, a w pliku song.mp3 są poprawne dane.

Ale, (jak zawsze, coś gdzieś musi polec) gdy wrzuce jako wejscie i wyjście stdin i stdout:
  1. <?php
  2. $sCommand = 'lame.exe --mp3input - -';
  3. $iCount = 0;
  4. $iSentCount = 0;
  5. $sFile = 'E:SharedDnB & BreakcoreKubrak-Obiebozza.mp3';
  6.  
  7. $aDescriptor = array(
  8.    0 => array("pipe", "r"),
  9.    1 => array("pipe", "w"),
  10.    2 => array("file", "./encoder_error.txt", "a")
  11. );
  12. $rProcess = proc_open($sCommand, $aDescriptor, $aPipes);
  13. if(is_resource($rProcess))
  14. {
  15.    $rFile = fopen($sFile,'r');
  16.    while(!feof($rFile))
  17.    {
  18.        $sData = fread($rFile,8192);
  19.        $iWrittenCount += fwrite($aPipes[0], $sData);
  20.        $iSentCount += strlen($sData);
  21.        echo $iSentCount."\n";
  22.    }
  23.  
  24.    echo "\n odczytano: ".$iSentCount." bajtow";
  25.    echo "\n zapisano:  ".$iWrittenCount." bajtow";
  26.    fclose($aPipes[0]);
  27.    fclose($rFile);
  28. }else throw new Exception('Nie otwarto procesu');
  29.  
  30. while(!feof($aPipes[1]))
  31.    $sReturned .= fread($aPipes[1],8192);
  32.  
  33. echo "\n otrzymano: ".strlen($sReturned)." bajtow";
  34. proc_close($rProcess);
  35. ?>

Zacina się przy pierwszym wykonaniu pętli na fwrite(). Tzn. nie idzie dalej.
Gdy umieszczę fwrite poza pętlą - to samo. Gdy zapiszę jedną paczkę danych odczytuje i zapisuje 8192 bajty, otrzymuje: 7914. (czyli niby ok).

Jakiś pomysł ? Najprawdopodobniej jest to wina lame, ale rozgryźć tego nie potrafię.

Zawartość encoder_error.txt:
Kod
ID3v2 found. Be aware that the ID3 tag is currently lost when transcoding.
LAME 3.98.2 32bits (http://www.mp3dev.org/)
CPU features: MMX (ASM used), SSE (ASM used), SSE2
Using polyphase lowpass filter, transition band: 16538 Hz - 17071 Hz
Encoding <stdin> to <stdout>
Encoding as 44.1 kHz j-stereo MPEG-1 Layer III (11x) 128 kbps qval=3
Error writing mp3 output
ucho
Spójrz na http://pl2.php.net/manual/en/function.proc-open.php#89338
Być może będziesz musiał ustawić wejście i wyjście na nieblokujące, i wykonywać na zmianę zapis/odczyt do pipe - pomimo tego, że pewnie nie odczytasz ani bajta póki lame nie skończy działać.
erix
AFAIK, to podobnie, jak przy odpalaniu ffmpeg. Ja korzystam z czegoś takiego (znalezione winksmiley.jpg):

  1. <?php
  2. # util to grab console app output
  3. function runExternal( $cmd, &$code ) {
  4.  
  5.    $descriptorspec = array(
  6.        0 => array("pipe", "r"),  // stdin is a pipe that the child will read from
  7.        1 => array("pipe", "w"),  // stdout is a pipe that the child will write to
  8.        2 => array("pipe", "w") // stderr is a file to write to
  9.    );
  10.    
  11.    $pipes= array();
  12.    $process = proc_open($cmd, $descriptorspec, $pipes);
  13.  
  14.    $output= "";
  15.  
  16.    if (!is_resource($process)) return false;
  17.  
  18.    #close child's input imidiately
  19.    fclose($pipes[0]);
  20.  
  21.    stream_set_blocking($pipes[1],false);
  22.    stream_set_blocking($pipes[2],false);
  23.  
  24.    $todo= array($pipes[1],$pipes[2]);
  25.  
  26.    while( true ) {
  27.        $read= array();
  28.        if( !feof($pipes[1]) ) $read[]= $pipes[1];
  29.        if( !feof($pipes[2]) ) $read[]= $pipes[2];
  30.  
  31.        if (!$read) break;
  32.  
  33.        $ready= stream_select($read, $write=NULL, $ex= NULL, 2);
  34.  
  35.        if ($ready === false) {
  36.            break; #should never happen - something died
  37.        }
  38.  
  39.        foreach ($read as $r) {
  40.            $s= fread($r,1024);
  41.            $output.= $s;
  42.        }
  43.    }
  44.  
  45.    fclose($pipes[1]);
  46.    fclose($pipes[2]);
  47.  
  48.    $code= proc_close($process);
  49.  
  50.    return $output;
  51. }
  52. ?>
carbolymer
Nie można ustawiać dla proc_open wejścia i wyjścia na nieblokujące. Próbowałem z ustawianiem bufora, nic, gdy użyję takiej konfiguracji deskryptora:
  1. <?php
  2. $aDescriptor = array(
  3.                    0 => array("pipe", "r"),
  4.                    1 => array("file", "./semaphore.mp3","w"),
  5.                    2 => array("file", "./encoder_error.txt", "w")
  6. ?>

dane lądują w semaphore.mp3.
Nie mam pojęcia w jakiej kolejności powinienem odczytywać dane, aby odbywało się to płynnie. Gdy próbowałem po fwrite użyć stream_get_contents() (lub fread() ) zacinało się na tej funkcji.

Za wszelkie pomysły lub sugestie będę wdzięczny. winksmiley.jpg
erix
Cytat
Nie można ustawiać dla proc_open wejścia i wyjścia na nieblokujące.

A próbowałeś? tongue.gif Ja tego gotowca znalazłem gdzieś w Sieci i działa bez żadnych błędów przy ffmpeg, przy lame podejrzewam, że również.
carbolymer
Próbowałem. Bez różnicy czy ustawie na blokujące, czy nie, zachowuje sie jak blokujące.
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.