mirror of
https://github.com/danog/MadelineProto.git
synced 2024-11-30 07:18:57 +01:00
Allow converting URLs and streams
This commit is contained in:
parent
df1e6b2ba8
commit
a9aeaedaf4
@ -388,6 +388,7 @@ Want to add your own open-source project to this list? [Click here!](https://doc
|
||||
* <a href="https://docs.madelineproto.xyz/API_docs/methods/messages.hideChatJoinRequest.html" name="messages.hideChatJoinRequest">Dismiss or approve a chat join request related to a specific chat or channel: messages.hideChatJoinRequest</a>
|
||||
* <a href="https://docs.madelineproto.xyz/API_docs/methods/messages.hideAllChatJoinRequests.html" name="messages.hideAllChatJoinRequests">Dismiss or approve all join requests related to a specific chat or channel: messages.hideAllChatJoinRequests</a>
|
||||
* <a href="https://docs.madelineproto.xyz/PHP/danog/MadelineProto/API.html#downloadtoresponse-array-string-filecallbackinterface-danog-madelineproto-eventhandler-message-messagemedia-amp-http-server-request-request-callable-cb-null-null-int-size-null-null-string-mime-null-null-string-name-null-amp-http-server-response" name="downloadToResponse">Download file to amphp/http-server response: downloadToResponse</a>
|
||||
* <a href="https://docs.madelineproto.xyz/PHP/danog/MadelineProto/API.html#downloadtoreturnedstream-mixed-messagemedia-callable-cb-null-int-offset-0-int-end-1-amp-bytestream-readablestream" name="downloadToReturnedStream">Download file to an amphp stream, returning it: downloadToReturnedStream</a>
|
||||
* <a href="https://docs.madelineproto.xyz/PHP/danog/MadelineProto/API.html#downloadtobrowser-array-string-filecallbackinterface-danog-madelineproto-eventhandler-message-messagemedia-null-callable-cb-null-null-int-size-null-null-string-name-null-null-string-mime-null-void" name="downloadToBrowser">Download file to browser: downloadToBrowser</a>
|
||||
* <a href="https://docs.madelineproto.xyz/PHP/danog/MadelineProto/API.html#downloadtocallable-mixed-messagemedia-callable-filecallbackinterface-callable-callable-cb-null-bool-seekable-true-int-offset-0-int-end-1-int-part_size-null-mixed" name="downloadToCallable">Download file to callable: downloadToCallable</a>
|
||||
* <a href="https://docs.madelineproto.xyz/PHP/danog/MadelineProto/API.html#downloadtodir-mixed-messagemedia-string-filecallbackinterface-dir-callable-cb-null-mixed" name="downloadToDir">Download file to directory: downloadToDir</a>
|
||||
|
@ -121,3 +121,5 @@ final class MemoryArray extends ArrayIterator implements DbArray
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
|
||||
class_alias(MemoryArray::class, '\\danog\\MadelineProto\\Db\\NullCache\\MemoryArray');
|
@ -142,3 +142,5 @@ final class MysqlArray extends SqlArray
|
||||
");
|
||||
}
|
||||
}
|
||||
|
||||
class_alias(MysqlArray::class, '\\danog\\MadelineProto\\Db\\NullCache\\MysqlArray');
|
@ -109,3 +109,5 @@ final class PostgresArray extends PostgresArrayBytea
|
||||
");
|
||||
}
|
||||
}
|
||||
|
||||
class_alias(PostgresArray::class, '\\danog\\MadelineProto\\Db\\NullCache\\PostgresArray');
|
@ -127,3 +127,5 @@ class PostgresArrayBytea extends SqlArray
|
||||
");
|
||||
}
|
||||
}
|
||||
|
||||
class_alias(PostgresArrayBytea::class, '\\danog\\MadelineProto\\Db\\NullCache\\PostgresArrayBytea');
|
||||
|
@ -155,3 +155,5 @@ final class RedisArray extends DriverArray
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class_alias(RedisArray::class, '\\danog\\MadelineProto\\Db\\NullCache\\RedisArray');
|
||||
|
48
src/Ogg.php
48
src/Ogg.php
@ -19,10 +19,15 @@ declare(strict_types=1);
|
||||
namespace danog\MadelineProto;
|
||||
|
||||
use Amp\ByteStream\ReadableStream;
|
||||
use Amp\File\Whence;
|
||||
use Amp\ByteStream\WritableStream;
|
||||
use Amp\Http\Client\HttpClientBuilder;
|
||||
use Amp\Http\Client\Request;
|
||||
use AssertionError;
|
||||
use danog\MadelineProto\Stream\BufferedStreamInterface;
|
||||
use danog\MadelineProto\Stream\BufferInterface;
|
||||
use danog\MadelineProto\Stream\Common\SimpleBufferedRawStream;
|
||||
use danog\MadelineProto\Stream\ConnectionContext;
|
||||
use danog\MadelineProto\Stream\Transport\PremadeStream;
|
||||
use FFI;
|
||||
use FFI\CData;
|
||||
use Webmozart\Assert\Assert;
|
||||
@ -498,7 +503,7 @@ final class Ogg
|
||||
|
||||
public static function convert(
|
||||
LocalFile|RemoteUrl|ReadableStream $wavIn,
|
||||
string $oggOut
|
||||
LocalFile|WritableStream $oggOut
|
||||
): void {
|
||||
$opus = FFI::cdef('
|
||||
typedef struct OpusEncoder OpusEncoder;
|
||||
@ -542,23 +547,33 @@ final class Ogg
|
||||
$checkErr($opus->opus_encoder_ctl($encoder, self::OPUS_SET_BANDWIDTH_REQUEST, self::OPUS_BANDWIDTH_FULLBAND));
|
||||
$checkErr($opus->opus_encoder_ctl($encoder, self::OPUS_SET_BITRATE_REQUEST, 130*1000));
|
||||
|
||||
$in = openFile($wavIn, 'r');
|
||||
Assert::eq($in->read(length: 4), 'RIFF', "A .wav file must be provided!");
|
||||
$totalLength = \unpack('V', $in->read(length: 4))[1];
|
||||
Assert::eq($in->read(length: 4), 'WAVE');
|
||||
$in = $wavIn instanceof LocalFile
|
||||
? openFile($wavIn->file, 'r')
|
||||
: (
|
||||
$wavIn instanceof RemoteUrl
|
||||
? HttpClientBuilder::buildDefault()->request(new Request($wavIn->url))->getBody()
|
||||
: $wavIn
|
||||
);
|
||||
|
||||
$ctx = (new ConnectionContext())->addStream(PremadeStream::class, $in)->addStream(SimpleBufferedRawStream::class);
|
||||
/** @var SimpleBufferedRawStream */
|
||||
$in = $ctx->getStream();
|
||||
Assert::eq($in->bufferRead(length: 4), 'RIFF', "A .wav file must be provided!");
|
||||
$totalLength = \unpack('V', $in->bufferRead(length: 4))[1];
|
||||
Assert::eq($in->bufferRead(length: 4), 'WAVE');
|
||||
do {
|
||||
$type = $in->read(length: 4);
|
||||
$length = \unpack('V', $in->read(length: 4))[1];
|
||||
$type = $in->bufferRead(length: 4);
|
||||
$length = \unpack('V', $in->bufferRead(length: 4))[1];
|
||||
if ($type === 'fmt ') {
|
||||
Assert::eq($length, 16);
|
||||
$contents = $in->read(length: $length + ($length % 2));
|
||||
$contents = $in->bufferRead(length: $length + ($length % 2));
|
||||
$header = \unpack('vaudioFormat/vchannels/VsampleRate/VbyteRate/vblockAlign/vbitsPerSample', $contents);
|
||||
Assert::eq($header['audioFormat'], 1);
|
||||
Assert::eq($header['sampleRate'], 48000);
|
||||
} elseif ($type === 'data') {
|
||||
break;
|
||||
} else {
|
||||
$in->seek($length, Whence::Current);
|
||||
$in->bufferRead($length);
|
||||
}
|
||||
} while (true);
|
||||
|
||||
@ -566,7 +581,9 @@ final class Ogg
|
||||
$chunkSize = (int) ($sampleCount * $header['channels'] * ($header['bitsPerSample'] >> 3));
|
||||
$shift = (int) \log($header['channels'] * ($header['bitsPerSample'] >> 3), 2);
|
||||
|
||||
$out = openFile($oggOut, 'w');
|
||||
$out = $oggOut instanceof LocalFile
|
||||
? openFile($oggOut->file, 'w')
|
||||
: $oggOut;
|
||||
|
||||
$writePage = function (int $header_type_flag, int $granule, int $streamId, int &$streamSeqno, string $packet) use ($out): void {
|
||||
Assert::true(\strlen($packet) < 65025);
|
||||
@ -638,19 +655,20 @@ final class Ogg
|
||||
|
||||
$granule = 0;
|
||||
$buf = FFI::cast(FFI::type('char*'), FFI::addr($opus->new('char[1024]')));
|
||||
while (!$in->eof()) {
|
||||
$chunk = \str_pad($in->read(length: $chunkSize), $chunkSize, "\0");
|
||||
do {
|
||||
$chunkOrig = $in->bufferRead(length: $chunkSize);
|
||||
$chunk = \str_pad($chunkOrig, $chunkSize, "\0");
|
||||
$granuleDiff = \strlen($chunk) >> $shift;
|
||||
$len = $opus->opus_encode($encoder, $chunk, $granuleDiff, $buf, 1024);
|
||||
$checkErr($len);
|
||||
$writePage(
|
||||
$in->eof() ? self::EOS : 0,
|
||||
\strlen($chunk) !== \strlen($chunkOrig) ? self::EOS : 0,
|
||||
$granule += $granuleDiff,
|
||||
$streamId,
|
||||
$seqno,
|
||||
FFI::string($buf, $len)
|
||||
);
|
||||
}
|
||||
} while (\strlen($chunk) === \strlen($chunkOrig));
|
||||
$opus->opus_encoder_destroy($encoder);
|
||||
unset($buf, $encoder, $opus);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user