prepare( "INSERT INTO streams (url, filename, dropbox_token, status) VALUES (:url, :filename, :token, 'pending')" ); $stmt->execute([ ':url' => $url, ':filename' => $filename, ':token' => $token ]); $newId = $pdo->lastInsertId(); http_response_code(201); $response['success'] = true; $response['message'] = 'Stream salvo com sucesso! Pronto para conversão.'; $response['job_id'] = $newId; } catch (PDOException $e) { http_response_code(500); $response['error'] = 'Erro no banco de dados: ' . $e->getMessage(); } } } else { http_response_code(405); $response['error'] = 'Método não permitido para esta ação.'; } break; case 'get_streams': try { $pdo = db(); $stmt = $pdo->query("SELECT id, url, filename, status, created_at FROM streams ORDER BY created_at DESC"); $streams = $stmt->fetchAll(PDO::FETCH_ASSOC); $response['success'] = true; $response['streams'] = $streams; } catch (PDOException $e) { http_response_code(500); $response['error'] = 'Erro no banco de dados: ' . $e->getMessage(); } break; case 'convert_to_mp4': if ($_SERVER['REQUEST_METHOD'] === 'POST') { $data = json_decode(file_get_contents('php://input'), true); $id = $data['id'] ?? null; if (empty($id)) { http_response_code(400); $response['error'] = 'O ID do stream é obrigatório.'; } else { try { $pdo = db(); $stmt = $pdo->prepare("SELECT url, filename FROM streams WHERE id = :id"); $stmt->execute([':id' => $id]); $stream = $stmt->fetch(PDO::FETCH_ASSOC); if (!$stream) { http_response_code(404); $response['error'] = 'Stream não encontrado.'; } else { $pdo->prepare("UPDATE streams SET status = 'converting' WHERE id = :id")->execute([':id' => $id]); $output_filename = pathinfo($stream['filename'], PATHINFO_FILENAME) . '_' . time() . '.mp4'; $output_path = __DIR__ . '/videos/' . $output_filename; if (!is_dir(__DIR__ . '/videos')) { mkdir(__DIR__ . '/videos', 0775, true); } $command = [ 'ffmpeg', '-i', $stream['url'], '-c:v', 'libx264', '-preset', 'veryfast', '-crf', '23', '-c:a', 'aac', '-b:a', '128k', $output_path ]; $process = new \Symfony\Component\Process\Process($command); $process->setTimeout(3600); $process->run(); if (!$process->isSuccessful()) { http_response_code(500); $error_output = $process->getErrorOutput(); $pdo->prepare("UPDATE streams SET status = 'error', error_message = :error WHERE id = :id")->execute([':error' => $error_output, ':id' => $id]); $response['error'] = 'Falha na conversão do vídeo.'; } else { $stmt = $pdo->prepare("UPDATE streams SET status = 'completed', converted_path = :converted_path WHERE id = :id"); $stmt->execute([ ':converted_path' => $output_filename, ':id' => $id ]); $response['success'] = true; $response['message'] = 'Vídeo convertido com sucesso!'; } } } catch (PDOException $e) { http_response_code(500); $response['error'] = 'Erro no banco de dados: ' . $e->getMessage(); } catch (\Exception $e) { http_response_code(500); $response['error'] = 'Erro na conversão: ' . $e->getMessage(); } } } else { http_response_code(405); $response['error'] = 'Método não permitido para esta ação.'; } break; case 'send_to_dropbox': if ($_SERVER['REQUEST_METHOD'] === 'POST') { $data = json_decode(file_get_contents('php://input'), true); $id = $data['id'] ?? null; $token = $data['token'] ?? null; if (empty($id) || empty($token)) { http_response_code(400); $response['error'] = 'O ID do stream e o token do Dropbox são obrigatórios.'; break; } try { $pdo = db(); $stmt = $pdo->prepare("SELECT converted_path FROM streams WHERE id = :id AND status = 'completed'"); $stmt->execute([':id' => $id]); $stream = $stmt->fetch(PDO::FETCH_ASSOC); if (!$stream || empty($stream['converted_path'])) { http_response_code(404); $response['error'] = 'Arquivo convertido não encontrado ou o stream não está completo.'; break; } $filePath = __DIR__ . '/videos/' . $stream['converted_path']; if (!file_exists($filePath)) { http_response_code(404); $response['error'] = 'Arquivo físico não encontrado no servidor.'; break; } /* COMO OBTER UM TOKEN DE ACESSO DO DROPBOX: 1. Vá para https://www.dropbox.com/developers/apps e clique em "Create app". 2. Escolha "Scoped Access". 3. Selecione "Full Dropbox" ou "App folder". 4. Dê um nome único à sua aplicação (ex: MeuConversorDeVideo). 5. Na aba "Permissions", marque as permissões: `files.content.write`. 6. Clique em "Submit". 7. Na aba "Settings", procure pela seção "Generated access token" e clique em "Generate". 8. Copie o token gerado e cole no campo "Token do Dropbox" na interface. */ $app = new \Dropbox\App("", "", $token); $dropbox = new \Dropbox\Client($app); $dropboxFileName = '/' . basename($filePath); $file = $dropbox->upload($filePath, $dropboxFileName, ['autorename' => true]); $response['success'] = true; $response['message'] = 'Arquivo enviado com sucesso para o Dropbox!'; $response['file_name'] = $file->getName(); } catch (PDOException $e) { http_response_code(500); $response['error'] = 'Erro no banco de dados: ' . $e->getMessage(); } catch (\Dropbox\Exception $e) { http_response_code(500); $response['error'] = 'Erro no Dropbox: ' . $e->getMessage(); } catch (Exception $e) { http_response_code(500); $response['error'] = 'Ocorreu um erro inesperado: ' . $e->getMessage(); } } else { http_response_code(405); $response['error'] = 'Método não permitido para esta ação.'; } break; default: http_response_code(400); $response['error'] = 'Ação não especificada ou inválida.'; break; case 'delete': if ($_SERVER['REQUEST_METHOD'] === 'POST') { $data = json_decode(file_get_contents('php://input'), true); $id = $data['id'] ?? null; if (empty($id)) { http_response_code(400); $response['error'] = 'O ID do stream é obrigatório.'; break; } try { $pdo = db(); $stmt = $pdo->prepare("SELECT converted_path FROM streams WHERE id = :id"); $stmt->execute([':id' => $id]); $stream = $stmt->fetch(PDO::FETCH_ASSOC); if ($stream && !empty($stream['converted_path'])) { $filePath = __DIR__ . '/videos/' . $stream['converted_path']; if (file_exists($filePath)) { unlink($filePath); } } $stmt = $pdo->prepare("DELETE FROM streams WHERE id = :id"); $stmt->execute([':id' => $id]); if ($stmt->rowCount() > 0) { $response['success'] = true; $response['message'] = 'Vídeo e registro apagados com sucesso!'; } else { http_response_code(404); $response['error'] = 'Nenhum vídeo encontrado com este ID.'; } } catch (PDOException $e) { http_response_code(500); $response['error'] = 'Erro no banco de dados: ' . $e->getMessage(); } catch (\Exception $e) { http_response_code(500); $response['error'] = 'Ocorreu um erro inesperado: ' . $e->getMessage(); } } else { http_response_code(405); $response['error'] = 'Método não permitido para esta ação.'; } break; } echo json_encode($response);